home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / exploits / irckill / patches / BitchX / dcc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-13  |  125.7 KB  |  4,412 lines

  1. /*
  2.  * dcc.c: Things dealing client to client connections. 
  3.  *
  4.  * Written By Troy Rollo <troy@cbme.unsw.oz.au> 
  5.  *
  6.  * Copyright(c) 1991 
  7.  *
  8.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  9.  * Heavily modified Colten Edwards 1996-97
  10.  */
  11.  
  12. /*
  13.  * april 11, 1998
  14.  * patched dcc overflow - nyt
  15. */
  16.  
  17.  
  18. #include "irc.h"
  19. #include <sys/stat.h>
  20. #include <stdarg.h>
  21. #include <stdio.h>
  22. #include <dirent.h>
  23.  
  24.  
  25. #include "ctcp.h"
  26. #include "crypt.h"
  27. #include "cdcc.h"
  28. #include "dcc.h"
  29. #include "hook.h"
  30. #include "ircaux.h"
  31. #include "lastlog.h"
  32. #include "newio.h"
  33. #include "output.h"
  34. #include "parse.h"
  35. #include "server.h"
  36. #include "status.h"
  37. #include "vars.h"
  38. #include "whois.h"
  39. #include "window.h"
  40. #include "screen.h"
  41. #include "ircterm.h"
  42. #include "hook.h"
  43. #include "misc.h"
  44. #include "tcl_bx.h"
  45. #include "userlist.h"
  46. #include "hash2.h"
  47.  
  48. #include <float.h>
  49. #ifdef WINNT
  50. #include <windows.h>
  51. #endif
  52.  
  53.  
  54. static    off_t        filesize = 0;
  55.  
  56. DCC_list *    ClientList = NULL;
  57.  
  58. static    char        DCC_current_transfer_buffer[BIG_BUFFER_SIZE/4];
  59. extern    int        dgets_errno;
  60.  
  61.  
  62. static    void         dcc_add_deadclient _((register DCC_list *));
  63. static    void         dcc_close _((char *, char *));
  64. static    void        dcc_getfile _((char *, char *));
  65.     int        dcc_open _((DCC_list *));
  66. static    void         dcc_really_erase _((void));
  67. static    void        dcc_rename _((char *, char *));
  68. static    void        dcc_send_raw _((char *, char *));
  69. static    void         output_reject_ctcp _((char *, char *));
  70. static    void        process_incoming_chat _((register DCC_list *));
  71. static    void        process_incoming_listen _((register DCC_list *));
  72. static    void        process_incoming_raw _((register DCC_list *));
  73. static    void        process_outgoing_file _((register DCC_list *, int));
  74. static    void        process_incoming_file _((register DCC_list *));
  75. static    void        DCC_close_filesend _((DCC_list *, char *));
  76. static    void        update_transfer_buffer _((char *format, ...));
  77.  
  78. #ifdef NON_BLOCKING_CONNECTS
  79. static    void    dcc_got_connected _((DCC_list *));
  80. #endif
  81.  
  82. static  void    dcc_update_stats _((DCC_list *));
  83. static    void    dcc_set_paths _((char *, char *));
  84. static  void    dcc_set_quiet _((char *, char *));
  85. static  void    dcc_tog_auto _((char *, char *));
  86. static    void    dcc_show_active _((char *, char *));
  87. static    void    dcc_help1 _((char *, char *));
  88.  
  89. static unsigned char byteordertest _((void));
  90. static void dcc_reject_notify _((char *, char *, char *));
  91. static    int    get_to_from _((char *));
  92.  
  93. static    char *strip_path _((char *));
  94. static    void dcc_tog_rename _((char *, char *)); 
  95. static    char *check_paths _((char *));
  96. static    void dcc_overwrite_toggle _((char *, char *));
  97.  
  98. static    void dcc_ftpget _((char *, char *));
  99. static    void dcc_ftpsend _((char *, char *));
  100. static    void dcc_nick _((char *, char *));
  101.  
  102. static    void process_outgoing_ftp _((DCC_list *));
  103. static    void process_incoming_ftp _((register DCC_list *));
  104. #ifdef FTP_XMIT
  105. static    void dcc_xmitget _((char *, char *, char *, char *));
  106. #endif
  107.  
  108. #ifdef MIRC_BROKEN_DCC_RESUME
  109.     void        dcc_getfile_resume _((char *, char *));
  110. static     void         dcc_getfile_resume_demanded _((char *user, char *filename, char *port, char *offset));
  111. static    void        dcc_getfile_resume_start _((char *nick, char *filename, char *port, char *offset));
  112. #endif
  113.  
  114.  
  115.  
  116. typedef void (*dcc_function) _((char *, char *));
  117. typedef struct
  118. {
  119.     char    *    name;
  120.     dcc_function     function;
  121.     char    *    help;
  122. } DCC_commands;
  123.  
  124. DCC_commands    *dcc_dllcommands = { NULL };
  125.  
  126. DCC_commands    dcc_commands[] =
  127. {
  128.     { "ACTIVE",    dcc_show_active,    "\n- Displays active dcc and limit" },
  129.     { "AUTO",    dcc_tog_auto,        "[on|off]\n- toggles auto-get on/off" },
  130.     { "AUTO_RENAME",dcc_tog_rename,        "[on|off]\n- toggles auto-rename on/off" },
  131. #ifndef PUBLIC_ACCESS
  132.     { "BOT",    dcc_chatbot,        "[nick]\n- Starts a dcc bot connection with another bx client" },
  133. #endif
  134.     { "CHAT",    dcc_chat,        "[nick]\n- Starts a dcc chat connection" },
  135.     { "LIST",    dcc_list,        "\n- Lists dcc's in old format" },
  136.     { "GLIST",    dcc_glist,        "\n- Lists dcc's in new format" },
  137.  
  138.     { "TSEND",    dcc_filesend,        "[nick|nick1,nick2,...] [filename] [[-e encrypt][-p port]]\n- TurboDCC sends filename to nick(s) using encrypt and port" },
  139.     { "SEND",    dcc_filesend,        "[nick|nick1,nick2,...] [filename] [[-e encrypt][-p port]]\n- DCC sends filename to nick(s) using encrypt and port"  },
  140.     { "RESEND",    dcc_resend,        "[nick|nick1,nick2,...] [filename] [[-e encrypt][-p port]]\n- DCC resends filename to nick(s) using encrypt and port"  }, 
  141.     { "TRESEND",    dcc_resend,        "[nick|nick1,nick2,...] [filename] [[-e encrypt][-p port]]\n- TurboDCC resends filename to nick(s) using encrypt and port"  }, 
  142.  
  143. #ifndef PUBLIC_ACCESS
  144.     { "GET",    dcc_getfile,        "[nick|nick1,nick2,...] [[filename][-e encrypt]]\n- DCC gets from nick(s) filename using encrypt if supplied" },
  145.     { "TGET",    dcc_getfile,        "[nick|nick1,nick2,...] [[filename][-e encrypt]]\n- TurboDCC gets from nick(s) filename using encrypt if supplied"  },
  146.     { "REGET",    dcc_regetfile,        "[nick|nick1,nick2,...] [[filename][-e encrypt]]\n- DCC regets from nick(s) filename using encrypt if supplied"  },
  147.     { "TREGET",    dcc_regetfile,        "[nick|nick1,nick2,...] [[filename][-e encrypt]]\n- TurboDCC regets from nick(s) filename using encrypt if supplied"  },
  148. #endif
  149.     { "CLOSE",    dcc_close,        "[#all|#|[send|get|resend|reget|nick #|#all|-all|filename][type]]\n- Closes a dcc connection"},
  150.     { "RENAME",    dcc_rename,        "[nick] [description] [new description]\n- Renames an incoming dcc file" },
  151.  
  152.  
  153. #ifdef MIRC_BROKEN_DCC_RESUME
  154.     { "RESUME",    dcc_getfile_resume,    "[nick|nick1,nick2,...] [file] [-e password]\n- DCC resumes a file ala mirc. NOTE autoget must be off"},
  155. #endif
  156.  
  157. #ifndef PUBLIC_ACCESS
  158.     { "RAW",    dcc_send_raw,        "[nick] <text>\n- Sends text to a dcc raw connection to [nick]" },
  159. #endif
  160.     { "QUIET",    dcc_set_quiet,        "[on|off]\n- toggle dcc quiet mode on/off" },
  161.     { "STATS",    dcc_stats,        "\n- Displays dcc stats for this session" },
  162.     { "PATHS",    dcc_set_paths,        "[on|off]\n- toggles display of paths on/off" },
  163. #ifndef PUBLIC_ACCESS
  164.     { "OVERWRITE",    dcc_overwrite_toggle,    "[on|off]\n- toggle overwrite of files on/off" },
  165. #ifdef WANT_FTP
  166.     { "FTP",    dcc_ftpopen ,        "[hostname] [[user] [passwd] [-p port]]\n- Starts a ftp connection to hostname" },
  167.  
  168.     { "XRECV",    dcc_ftpget,        "experimental" },
  169.     { "XSEND",    dcc_ftpsend,        "experimental" },
  170. #endif
  171. #endif
  172.     { "EXEMPT",    dcc_nick,        "[+nick|+nick1,+nick2,...|nick|nick1,nick2,...]\n- Adds or removes nick(s) to the dcc exempt list which bypasses autoget" },
  173.  
  174.     { "HELP",    dcc_help1,        "help" },
  175.     { NULL,        (dcc_function) NULL,    NULL }
  176. };
  177.  
  178. #define BAR_LENGTH 50
  179. static    int    dcc_count = 1;
  180.     int    dcc_active_count = 0;
  181. static    int    doing_multi = 0;
  182. static    int    dcc_quiet = 0;
  183. static    int    dcc_paths = 0;
  184. static    int    dcc_overwrite_var = 0;
  185.     double    dcc_bytes_in = 0;
  186.     double    dcc_bytes_out = 0;
  187.     double  dcc_max_rate_in = 0.0;
  188. static     double  dcc_min_rate_in = DBL_MAX;
  189.     double  dcc_max_rate_out = 0.0;
  190. static     double  dcc_min_rate_out = DBL_MAX;
  191.  
  192.      unsigned int    send_count_stat = 0;
  193.     unsigned int    get_count_stat = 0;
  194.  
  195.     char    *last_chat_req = NULL;
  196.  
  197. #define DCC_HASHSIZE 11
  198. HashEntry dcc_no_flood[DCC_HASHSIZE];
  199.  
  200.  
  201. char    *dcc_types[] =
  202. {
  203.     "<none>",
  204.     "CHAT",
  205.     "SEND",
  206.     "GET",
  207.     "RAW_LISTEN",
  208.     "RAW",
  209.     "RESEND",
  210.     "REGET",
  211.     "BOT",
  212.     "FTP",
  213.     "FTPGET",
  214.     "FTPSEND",
  215.     "XMITSEND",
  216.     "XMITRECV",
  217.     NULL
  218. };
  219.  
  220. struct    deadlist
  221. {
  222.     DCC_list *it;
  223.     struct deadlist *next;
  224. }    *deadlist = NULL;
  225.  
  226.  
  227.  
  228. static int dccBlockSize(void)
  229. {
  230. register int BlockSize, NewBlockSize;
  231.     NewBlockSize = BlockSize = get_int_var(DCC_BLOCK_SIZE_VAR);
  232.     if (BlockSize > 2048)
  233.         BlockSize = 2048;
  234.     else if (BlockSize < 16)
  235.         BlockSize = 16;
  236.     else if ((BlockSize % 2) != 0)
  237.     {
  238.         BlockSize = 8;
  239.         while (BlockSize <= NewBlockSize)
  240.             BlockSize *= 2;
  241.     }
  242.     if (NewBlockSize != BlockSize)
  243.         set_int_var(DCC_BLOCK_SIZE_VAR, BlockSize);
  244.     return (BlockSize);
  245. }
  246. /*
  247.  * dcc_searchlist searches through the dcc_list and finds the client
  248.  * with the the flag described in type set.
  249.  */
  250. DCC_list *dcc_searchlist(char *name, char *user, unsigned type, unsigned flag, char *othername, char *userhost, int active)
  251. {
  252.     register DCC_list **Client = NULL, *NewClient = NULL;
  253.     
  254.     int dcc_num = 0;
  255.     if (user && *user == '#' && my_atol(user+1)) 
  256.     {
  257.         /* we got a number so find that instead */
  258.         char *p;
  259.         p = user;
  260.         p++;
  261.         dcc_num = my_atol(p);
  262.         if (dcc_num > 0)
  263.         {
  264.             for(Client = (&ClientList); *Client; Client = (&(**Client).next))
  265.                 if (dcc_num && ((**Client).dccnum == dcc_num))
  266.                     return *Client;
  267.         }
  268.     } 
  269.     else
  270.     {
  271.     for (Client = (&ClientList); *Client ; Client = (&(**Client).next))
  272.     {
  273.         /* 
  274.          * The following things have to be true:
  275.          * -> The types have to be the same
  276.          * -> One of the following things is true:
  277.          *      -> `name' is NULL or `name' is the same as the 
  278.          *       entry's description
  279.          *          *OR*
  280.          *    -> `othername' is the same as the entry's othername
  281.          * -> `user' is the same as the entry's user-perr
  282.          * -> One of the following is true:
  283.          *    -> `active' is 1 and the entry is active
  284.          *    -> `active' is 0 and the entry is not active
  285.          *    -> `active' is -1 (dont care)
  286.          */
  287.         if (
  288.              ( ((**Client).flags & DCC_TYPES) == type ) &&
  289.              ( (!name || ((**Client).description && !my_stricmp(name, (**Client).description))) ||
  290.                (othername && (**Client).othername && !my_stricmp(othername, (**Client).othername))   ) &&
  291.              ( user && !my_stricmp(user, (**Client).user) ) &&
  292.              (  (active == -1) ||
  293.                ((active == 0) && !((**Client).flags & DCC_ACTIVE)) ||
  294.                ((active == 1) && ((**Client).flags & DCC_ACTIVE))
  295.              )
  296.            )
  297.             return *Client;
  298.     }
  299.     }
  300.     if (!flag)
  301.         return NULL;
  302.     *Client = NewClient = (DCC_list *) new_malloc(sizeof(DCC_list));
  303.     NewClient->flags = type;
  304.     NewClient->read = NewClient->write = NewClient->file = -1;
  305.     NewClient->filesize = filesize;
  306.     malloc_strcpy(&NewClient->description, name);
  307.     malloc_strcpy(&NewClient->user, user);
  308.     malloc_strcpy(&NewClient->othername, othername);
  309.     malloc_strcpy(&NewClient->userhost, userhost);
  310.     NewClient->packets_total = filesize ? (filesize / (dccBlockSize() + 1)) : 0;
  311.     get_time(&NewClient->lasttime);
  312.     if (dcc_count == 0) dcc_count = 1;
  313.     NewClient->dccnum = dcc_count++;
  314.     return NewClient;
  315. }
  316.  
  317. /*
  318.  * Added by Chaos: Is used in edit.c for checking redirect.
  319.  */
  320. extern int    dcc_active (char *user)
  321. {
  322.     return (dcc_searchlist("chat", user, DCC_CHAT, 0, NULL, NULL, 1)) ? 1 : 0;
  323. }
  324.  
  325. extern int    dcc_activebot (char *user)
  326. {
  327.     return (dcc_searchlist("chat", user, DCC_BOTMODE, 0, NULL, NULL, 1)) ? 1 : 0;
  328. }
  329.  
  330. extern int    dcc_activeraw (char *user)
  331. {
  332.     return (dcc_searchlist(/*"RAW"*/NULL, user, DCC_RAW, 0, NULL, NULL, 1)) ? 1 : 0;
  333. }
  334.  
  335.  
  336. static    void dcc_add_deadclient(register DCC_list *client)
  337. {
  338.     struct deadlist *new;
  339.  
  340.     new = (struct deadlist *) new_malloc(sizeof(struct deadlist));
  341.     new->next = deadlist;
  342.     new->it = client;
  343.     deadlist = new;
  344. }
  345.  
  346. /*
  347.  * dcc_erase searches for the given entry in the dcc_list and
  348.  * removes it
  349.  */
  350. int dcc_erase(DCC_list *Element)
  351. {
  352.     register DCC_list    **Client;
  353.     int        erase_one = 0;
  354.     dcc_count = 1;
  355.         
  356.     for (Client = &ClientList; *Client; Client = &(**Client).next)
  357.     {
  358.         if (*Client == Element)
  359.         {
  360.             *Client = Element->next;
  361.             if (Element->write != -1) 
  362.                 FD_CLR(Element->write, &writables);
  363.             Element->read = new_close(Element->read);
  364.             Element->file = new_close(Element->file);
  365.             new_free(&Element->othername);
  366.             new_free(&Element->description);
  367.             new_free(&Element->userhost);
  368.             new_free(&Element->user);
  369.             new_free(&Element->buffer);
  370.             new_free(&Element->encrypt);
  371.             new_free(&Element->cksum);
  372.             new_free(&Element->dccbuffer);
  373.             if (Element->dcc_handler)
  374.                 (Element->dcc_handler)(NULL, NULL);
  375.             new_free((char **)&Element);
  376.             erase_one++;
  377.             break;
  378.         }
  379.     }
  380.     for (Client = &ClientList; *Client; Client = &(**Client).next)
  381.         (*Client)->dccnum = dcc_count++;
  382.     if (erase_one)
  383.     {
  384.         *DCC_current_transfer_buffer = 0;
  385.     }
  386.     return erase_one;
  387. }
  388.  
  389. static void dcc_really_erase _((void))
  390. {
  391.     struct deadlist *dies = NULL;
  392.     for (;(dies = deadlist) != NULL;)
  393.     {
  394.         deadlist = deadlist->next;
  395.         dcc_erase(dies->it);
  396.         new_free(&dies);
  397.     }
  398. }
  399.  
  400. /*
  401.  * Set the descriptor set to show all fds in Client connections to
  402.  * be checked for data.
  403.  */
  404. extern void    set_dcc_bits (fd_set *rd, fd_set *wd)
  405. {
  406.     register DCC_list    *Client;
  407.     unsigned int flag;
  408.     unsigned int fast_dcc = get_int_var(DCC_FAST_VAR);
  409.         
  410.     for (Client = ClientList; Client != NULL; Client = Client->next)
  411.     {
  412.  
  413.         flag = Client->flags & DCC_TYPES;
  414.         if (Client->write > -1)
  415.         {
  416. #ifdef NON_BLOCKING_CONNECTS
  417. #ifdef DCC_CNCT_PEND
  418.             if (Client->flags & DCC_CNCT_PEND)
  419.                 FD_SET(Client->write, wd);
  420.             else 
  421. #endif
  422.             if (((flag == DCC_FILEOFFER) || 
  423.                     (flag == DCC_RESENDOFFER) ||
  424.                     (flag == DCC_FTPSEND)) && 
  425.                     !Client->eof && fast_dcc)
  426.                 FD_SET(Client->write, wd);
  427. #endif
  428.         }
  429.         if (Client->read > -1)
  430.             FD_SET(Client->read, rd);
  431.     }
  432.     if  (!ClientList && dcc_active_count) 
  433.         dcc_active_count = 0; /* A HACK */
  434. }
  435.  
  436. #ifdef NON_BLOCKING_CONNECTS
  437. static    void dcc_got_connected(DCC_list *client)
  438. {
  439. struct sockaddr_in    remaddr = {0};
  440. int    rl = sizeof(remaddr);
  441.  
  442.     if (getpeername(client->read, (struct sockaddr *) &remaddr, &rl) != -1)
  443.     {
  444.  
  445.         FD_CLR(client->read, &writables);
  446.         if (client->flags & DCC_OFFER)
  447.         {
  448.             client->flags &= ~DCC_OFFER;
  449.  
  450.             if ((client->flags & DCC_TYPES) != DCC_RAW)
  451.             {
  452.  
  453.                 if (do_hook(DCC_CONNECT_LIST, "%s %s %s %d", client->user,
  454.                     dcc_types[client->flags&DCC_TYPES],inet_ntoa(remaddr.sin_addr),
  455.                     ntohs(remaddr.sin_port))) 
  456.                 {
  457.                     if (!dcc_quiet)
  458.                         put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  459.                         "%s %s %s %s %s %d", update_clock(GET_TIME), 
  460.                         dcc_types[client->flags&DCC_TYPES], client->user, 
  461.                         client->userhost?client->userhost:"u@h", inet_ntoa(remaddr.sin_addr), (int) ntohs(remaddr.sin_port)));
  462.                 }
  463.  
  464.             }
  465.         }
  466.         get_time(&client->starttime);
  467.         client->flags &= ~DCC_CNCT_PEND;
  468.         if (((client->flags & DCC_TYPES) == DCC_REGETFILE))
  469.         {
  470.                 /* send a packet to the sender with transfer resume instructions */
  471.             put_it("%s", convert_output_format("$G %RDCC %YTelling uplink we want to start at%n: $0", "%l", client->transfer_orders.byteoffset));
  472.                        send(client->read, (const char *)&client->transfer_orders, sizeof(struct transfer_struct), 0);
  473.         } 
  474.         else if (((client->flags & DCC_TYPES) == DCC_FTPOPEN))
  475.         {
  476.             if ((dcc_printf(client->read, "user %s\n", client->othername) < 0) || (dcc_printf(client->read, "pass %s\n", client->encrypt) < 0))
  477.             {
  478.                 client->flags |= DCC_DELETE;
  479.                 put_it(convert_output_format("%gFTP%n command failed write", NULL, NULL));
  480.                 new_free(&client->encrypt);
  481.                 return;
  482.             }
  483.             client->flags &= ~DCC_WAIT;
  484.             client->flags |= DCC_ACTIVE;
  485.             dcc_printf(client->read, "type i\n");
  486.             new_free(&client->encrypt);
  487.             return;
  488.         }
  489.         if (!get_int_var(DCC_FAST_VAR) && !(client->flags & DCC_TDCC))
  490.         {
  491.             set_blocking(client->read);
  492.             if (client->read != client->write)
  493.                 set_blocking(client->write);
  494.         }
  495.     }
  496.     
  497. }
  498. #endif
  499.  
  500. /*
  501.  * Check all DCCs for data, and if they have any, perform whatever
  502.  * actions are required.
  503.  */
  504. extern void    dcc_check (fd_set *Readables, fd_set *Writables)
  505. {
  506.     register DCC_list    **Client;
  507.     int    previous_server;
  508.     int    lastlog_level;
  509.     register int    flags;
  510. #ifdef NON_BLOCKING_CONNECTS
  511.     int    fast_dcc = get_int_var(DCC_FAST_VAR);
  512. #endif
  513.         
  514.  
  515.     for (Client = (&ClientList); *Client != NULL;)
  516.     {
  517.         flags = (*Client)->flags;
  518. #ifdef NON_BLOCKING_CONNECTS
  519. #ifdef DCC_CNCT_PEND
  520.         if (flags & DCC_CNCT_PEND)
  521.             dcc_got_connected(*Client);
  522. #endif
  523.         if (fast_dcc && ((flags & DCC_TYPES) != DCC_RAW_LISTEN) && (*Client)->write != -1 && FD_ISSET((*Client)->write, Writables))
  524.         {
  525.             FD_CLR((*Client)->write, Writables);
  526.             switch(flags & DCC_TYPES)
  527.             {
  528.  
  529. #ifdef WANT_FTP
  530.                 case DCC_FTPSEND:
  531.                     process_outgoing_ftp(*Client);
  532.                     break;
  533. #endif
  534.                 case DCC_RESENDOFFER:
  535.                 case DCC_FILEOFFER:
  536.                     process_outgoing_file(*Client, 0);
  537.             }
  538.         }
  539. #endif
  540.         if (!(flags & DCC_DELETE) && (*Client)->read != -1)
  541.         {
  542.             previous_server = from_server;
  543.             from_server = -1;
  544.             message_from(NULL, LOG_DCC);
  545.             lastlog_level = set_lastlog_msg_level(LOG_DCC);
  546.  
  547.             if (FD_ISSET((*Client)->read, Readables))
  548.             {
  549.                 FD_CLR((*Client)->read, Readables);
  550.                 switch(flags&DCC_TYPES)
  551.                 {
  552.                     case DCC_BOTMODE:
  553.                     case DCC_CHAT:
  554.                         from_server = previous_server;
  555.                         process_incoming_chat(*Client);
  556.                         from_server = -1;
  557.                         break;
  558.                     case DCC_RAW_LISTEN:
  559.                         process_incoming_listen(*Client);
  560.                         break;
  561.                     case DCC_RAW:
  562.                         process_incoming_raw(*Client);
  563.                         break;
  564.                     case DCC_FILEOFFER:
  565.                     case DCC_RESENDOFFER:
  566.                         process_outgoing_file(*Client, 1);
  567.                         break;
  568.                     case DCC_FILEREAD:
  569.                     case DCC_REGETFILE:
  570.                         process_incoming_file(*Client);
  571.                         break;
  572. #ifdef WANT_FTP
  573.                     case DCC_FTPOPEN:
  574.                     case DCC_FTPGET:
  575.                         process_incoming_ftp(*Client);
  576.                         break;
  577.                     case DCC_FTPSEND:
  578.                         process_outgoing_ftp(*Client);
  579.                         break;
  580.                     case DCC_XMITSEND:
  581.                     case DCC_XMITRECV:
  582.                         break;
  583. #endif
  584.                 }
  585.             }
  586.             message_from(NULL, LOG_CRAP);
  587.             (void) set_lastlog_msg_level(lastlog_level);
  588.             from_server = previous_server;
  589.         }
  590.         if (flags & DCC_DELETE)
  591.             dcc_add_deadclient(*Client);
  592.         Client = (&(**Client).next);
  593.     }
  594.     dcc_really_erase();
  595. }
  596.  
  597. /*
  598.  * Process a DCC command from the user.
  599.  */
  600. extern void    process_dcc(char *args)
  601. {
  602.     char    *command;
  603.     int    i;
  604.     int    lastlog_level;
  605.  
  606.     if (!(command = next_arg(args, &args)))
  607.         return;
  608.     for (i = 0; dcc_commands[i].name != NULL; i++)
  609.     {
  610.         if (!my_stricmp(dcc_commands[i].name, command))
  611.         {
  612.             message_from(NULL, LOG_DCC);
  613.             lastlog_level = set_lastlog_msg_level(LOG_DCC);
  614.             dcc_commands[i].function(dcc_commands[i].name, args);
  615.             message_from(NULL, LOG_CRAP);
  616.             (void) set_lastlog_msg_level(lastlog_level);
  617.             return;
  618.         }
  619.     }
  620.     put_it("%s", convert_output_format("$G Unknown %RDCC%n command: $0", "%s", command));
  621. }
  622.  
  623. int dcc_open _((DCC_list *Client))
  624. {
  625. char            *user,
  626.             *Type;
  627. struct    in_addr     myip;
  628. struct    sockaddr_in    remaddr;
  629. int            rl = sizeof(remaddr);
  630. int            old_server;
  631.  
  632.     user = Client->user;
  633.     old_server = from_server;
  634.  
  635.     if (from_server == -1)
  636.         from_server = get_window_server(0);
  637.  
  638.     myip.s_addr = server_list[from_server].local_addr.s_addr;
  639.  
  640. #if 0
  641.     if (myip.s_addr == htonl(0x00000000) || myip.s_addr == htonl(0x7f000001))
  642.         myip.s_addr = MyHostAddr.s_addr;
  643. #endif        
  644.     Type = dcc_types[Client->flags & DCC_TYPES];
  645.     if (Client->flags & DCC_TDCC)
  646.     {
  647.         switch(Client->flags & DCC_TYPES)
  648.         {
  649.             case DCC_FILEOFFER:
  650.                 Type = "TSEND";
  651.                 break;
  652.             case DCC_FILEREAD:
  653.                 Type = "TGET";
  654.                 break;
  655.             case DCC_RESENDOFFER:
  656.                 Type = "TRESEND";
  657.                 break;
  658.             case DCC_REGETFILE:
  659.                 Type = "TREGET";
  660.                 break;
  661.         }
  662.     }
  663.  
  664.  
  665.     if (Client->flags & DCC_OFFER)
  666.     {
  667.         message_from(NULL, LOG_DCC);
  668. #ifdef DCC_CNCT_PEND
  669.         Client->flags |= DCC_CNCT_PEND;
  670. #endif
  671.     /*BLAH!*/
  672.         Client->remport = ntohs(Client->remport);
  673. #ifdef WINNT
  674.         if ((Client->write = connect_by_number(inet_ntoa(Client->remote), &Client->remport, SERVICE_CLIENT, PROTOCOL_TCP, 0)) < 0)
  675. #else
  676.         if ((Client->write = connect_by_number(inet_ntoa(Client->remote), &Client->remport, SERVICE_CLIENT, PROTOCOL_TCP, 1)) < 0)
  677. #endif
  678.         {
  679.             put_it("%s", convert_output_format("$G %RDCC%n Unable to create connection: $0-", "%s", errno ? strerror(errno) : "Unknown Host"));
  680.             message_from(NULL, LOG_CRAP);
  681.             dcc_erase(Client);
  682.             from_server = old_server;
  683.             return 0;
  684.         }
  685.     /* BLAH! */
  686.         Client->remport = htons(Client->remport);
  687.         Client->read = Client->write;
  688.         new_open(Client->read);
  689.         Client->flags |= DCC_ACTIVE;
  690.         if ((getpeername(Client->read, (struct sockaddr *) &remaddr, &rl)) != -1)
  691.         {
  692.  
  693.             Client->flags &= ~DCC_OFFER;
  694.             if (get_to_from(Type) != -1)
  695.                 dcc_active_count++;
  696.             if ((Client->flags & DCC_TYPES) != DCC_RAW)
  697.             {
  698.                             if (do_hook(DCC_CONNECT_LIST,"%s %s %s %d",
  699.                                        user, Type, inet_ntoa(remaddr.sin_addr),
  700.                                        ntohs(remaddr.sin_port)))
  701.                     if (!dcc_quiet)
  702.                         put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  703.                             "%s %s %s %s %s %d", update_clock(GET_TIME), Type, user, Client->userhost?Client->userhost:"u@h", 
  704.                             inet_ntoa(remaddr.sin_addr), (int)ntohs(remaddr.sin_port)));
  705.             }
  706.         }
  707.         message_from(NULL, LOG_CRAP);
  708.         get_time(&Client->starttime);
  709.         Client->bytes_read = Client->bytes_sent = 0L;
  710.         from_server = old_server;
  711.         return 1;
  712.     }
  713.     else
  714.     {
  715.         unsigned short portnum = Client->local_port;
  716.  
  717. #ifdef DCC_CNCT_PEND
  718.         Client->flags |= DCC_WAIT|DCC_CNCT_PEND;
  719. #else
  720.         Client->flags |= DCC_WAIT;
  721. #endif
  722.         if (Client->remport)
  723.             portnum = Client->remport;
  724.             
  725.         message_from(NULL, LOG_DCC);
  726. #ifdef WINNT
  727.         if ((Client->read = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 0)) < 0)
  728. #else
  729.         if ((Client->read = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1)) < 0)
  730. #endif
  731.         {
  732.             put_it("%s", convert_output_format("$G %RDCC%n Unable to create connection: $0-", "%s", errno ? strerror(errno) : "Unknown Host"));
  733.             message_from(NULL, LOG_CRAP);
  734.             dcc_erase(Client);
  735.             from_server = old_server;
  736.             return 0;
  737.         }
  738.         if (get_to_from(Type) != -1)
  739.             dcc_active_count++;
  740.         if (Client->flags & DCC_TWOCLIENTS)
  741.         {
  742.             /* patch to NOT send pathname accross */
  743.             char    *nopath;
  744.  
  745. #if defined(WINNT) || defined(__EMX__)
  746.             if ( ((Client->flags & DCC_FILEOFFER)== DCC_FILEOFFER) && ((nopath = strrchr(Client->description, '\\')) || (nopath = strrchr(Client->description, '/')) ))
  747. #else
  748.             if (((Client->flags & DCC_FILEOFFER)== DCC_FILEOFFER) && (nopath = strrchr(Client->description, '/')))
  749. #endif
  750.                 nopath++;
  751.             else
  752.                 nopath = Client->description;
  753.  
  754.             if (Client->filesize)
  755.                 send_ctcp(CTCP_PRIVMSG, user, CTCP_DCC,
  756.                      "%s %s %lu %u %lu", Type, nopath,
  757.                      (u_long) ntohl(myip.s_addr),
  758.                      (u_short) portnum,
  759.                      (unsigned long)Client->filesize);
  760.             else if ((Client->flags & DCC_TYPES) == DCC_BOTMODE)
  761.                 send_ctcp(CTCP_NOTICE, user, CTCP_BOTLINK,
  762.                      "%s %s %lu %u %s", Type, nopath,
  763.                      (u_long) ntohl(myip.s_addr),
  764.                      (u_short) portnum, Client->encrypt?Client->encrypt:"");
  765.             else
  766.                 send_ctcp(CTCP_PRIVMSG, user, CTCP_DCC,
  767.                      "%s %s %lu %u", Type, nopath,
  768.                      (u_long) ntohl(myip.s_addr),
  769.                      (u_short) portnum);
  770.             message_from(NULL, LOG_DCC);
  771.             if (!doing_multi && !dcc_quiet)
  772.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET), 
  773.                     "%s %s %s", update_clock(GET_TIME), Type, user));
  774.             message_from(NULL, LOG_CRAP);
  775.         }
  776. #ifdef MIRC_BROKEN_DCC_RESUME
  777.         malloc_strcpy(&Client->othername, ltoa(portnum));
  778. #endif
  779.         new_open(Client->read);
  780.         Client->starttime.tv_sec = Client->starttime.tv_usec = 0;
  781.         Client->local_port = portnum;
  782.         from_server = old_server;
  783.         return 2;
  784.     }
  785.     message_from(NULL, LOG_CRAP);
  786. }
  787. void add_userhost_to_dcc(WhoisStuff *stuff, char *nick, char *args)
  788. {
  789. DCC_list *Client;
  790.     Client = dcc_searchlist("chat", nick, DCC_CHAT, 0, NULL, NULL, -1);
  791.     if (!stuff || !nick || !stuff->nick || !stuff->user || !stuff->host || !strcmp(stuff->user, "<UNKNOWN>"))
  792.         return;
  793.     if (Client)    
  794.         Client->userhost = m_sprintf("%s@%s", stuff->user, stuff->host);
  795.     return;
  796. }
  797.  
  798. void    dcc_chat (char *command, char *args)
  799. {
  800.     char    *user;
  801.     char     *nick;
  802.     
  803.     char    *passwd = NULL;
  804.     char    *port     = NULL;
  805.     char    *equal_user = NULL;
  806.     DCC_list    *Client;
  807.     
  808.     if ((user = next_arg(args, &args)) == NULL)
  809.     {
  810.         put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC chat", NULL, NULL));
  811.         return;
  812.     }
  813.     while (args && *args)
  814.     {
  815.         char *argument = next_arg(args, &args);
  816.         if (argument && strlen(argument) >= 2)
  817.         {
  818.             if (argument[0] == '-' || argument[1] == 'e')
  819.                 passwd = next_arg(args, &args);
  820.             else if (argument[0] == '-' || argument[1] == 'p')
  821.                 port = next_arg(args, &args);
  822.         }
  823.     }
  824.  
  825.     while ((nick = next_in_comma_list(user, &user)))
  826.     {
  827.         if (!nick || !*nick)
  828.             break;
  829.     
  830.         Client = dcc_searchlist("chat", nick, DCC_CHAT, 1, NULL, NULL, -1);
  831.  
  832.         if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  833.         {
  834.             put_it("%s", convert_output_format("$G %RDCC%n A previous DCC chat to $0 exists", "%s", nick));
  835.             return;
  836.         }
  837.         if (port)
  838.             Client->remport = atol(port);
  839.         Client->flags |= DCC_TWOCLIENTS;
  840.         if (passwd)
  841.             Client->encrypt = m_strdup(passwd);
  842.         equal_user = alloca(strlen(nick)+4);
  843.         strcpy(equal_user, "="); strcat(equal_user, nick);
  844.         addtabkey(equal_user, "msg", 0);
  845.  
  846.         dcc_open(Client);
  847.         add_to_userhost_queue(nick, add_userhost_to_dcc, "%d %s", Client->read, nick);
  848.     }
  849. }
  850.  
  851.  
  852. void    dcc_chatbot (char *command, char *args)
  853. {
  854.     char    *user;
  855.     char    *passwd = NULL;
  856.     DCC_list    *Client;
  857.     char    *port     = NULL;
  858.     
  859.     if ((user = next_arg(args, &args)) == NULL)
  860.     {
  861.         put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC bot", NULL, NULL));
  862.         return;
  863.     }
  864.     while (args && *args)
  865.     {
  866.         char *argument = next_arg(args, &args);
  867.         if (argument && argument[0] == '-' && strlen(argument) >=2)
  868.         {
  869.             if ((*(argument+1)) == 'e')
  870.                 passwd = next_arg(args, &args);
  871.             else if ((*(argument+1)) == 'p')
  872.                 port = next_arg(args, &args);
  873.         }
  874.     }
  875.         
  876.     Client = dcc_searchlist("chat", user, DCC_BOTMODE, 1, NULL, NULL, -1);
  877.  
  878.     if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  879.     {
  880.         put_it("%s", convert_output_format("$G %RDCC%n A previous DCC Bot to $0 exists", "%s", user));
  881.         return;
  882.     }
  883.     Client->flags |= DCC_TWOCLIENTS;
  884.     if (passwd)
  885.         Client->encrypt = m_strdup(passwd);
  886.     if (port)
  887.         Client->remport = atol(port);
  888.     dcc_open(Client);
  889.     add_to_userhost_queue(user, add_userhost_to_dcc, "%d %s", Client->read, user);
  890. }
  891.  
  892. extern char    *dcc_raw_listen (int port)
  893. {
  894.     DCC_list    *Client;
  895.     char    *PortName;
  896.     struct    sockaddr_in locaddr;
  897.     char    *RetName = NULL;
  898.     int    size;
  899.     int    lastlog_level;
  900.  
  901.     lastlog_level = set_lastlog_msg_level(LOG_DCC);
  902.     if (port && port < 1025)
  903.     {
  904.         put_it("%s", convert_output_format("$G %RDCC%n Cannot bind to a privileged port", NULL, NULL));
  905.         (void) set_lastlog_msg_level(lastlog_level);
  906.         return NULL;
  907.     }
  908.     PortName = ltoa(port);
  909.     Client = dcc_searchlist("raw_listen", PortName, DCC_RAW_LISTEN, 1, NULL, NULL, -1);
  910.     if (Client->flags & DCC_ACTIVE)
  911.     {
  912.         put_it("%s", convert_output_format("$G %RDCC%n A previous Raw Listen on $0 exists", "%s", PortName));
  913.         set_lastlog_msg_level(lastlog_level);
  914.         return RetName;
  915.     }
  916.     memset((char *) &locaddr, 0, sizeof(locaddr));
  917.     locaddr.sin_family = AF_INET;
  918.     locaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  919.     locaddr.sin_port = htons(port);
  920.     if (0 > (Client->read = socket(AF_INET, SOCK_STREAM, 0)))
  921.     {
  922.         dcc_erase(Client);
  923.         put_it("%s", convert_output_format("$G %RDCC%n socket() failed: $0-", "%s", strerror(errno)));
  924.         (void) set_lastlog_msg_level(lastlog_level);
  925.         return RetName;
  926.     }
  927.  
  928.     new_open(Client->read);
  929.     set_socket_options(Client->read);
  930.     if (bind(Client->read, (struct sockaddr *) &locaddr, sizeof(locaddr)) == -1)
  931.     {
  932.         dcc_erase(Client);
  933.         put_it("%s", convert_output_format("$G %RDCC%n Could not bind port: $0-", "%s", strerror(errno)));
  934.         (void) set_lastlog_msg_level(lastlog_level);
  935.         return RetName;
  936.     }
  937.     listen(Client->read, 4);
  938.     size = sizeof(locaddr);
  939.     get_time(&Client->starttime);
  940.     getsockname(Client->read, (struct sockaddr *) &locaddr, &size);
  941.     Client->write = ntohs(locaddr.sin_port); 
  942.     Client->flags |= DCC_ACTIVE;
  943.     malloc_strcpy(&Client->user, ltoa(Client->write));
  944.     malloc_strcpy(&RetName, Client->user);
  945.     (void) set_lastlog_msg_level(lastlog_level);
  946.     return RetName;
  947. }
  948.  
  949. extern char    *dcc_raw_connect(char *host, u_short port)
  950. {
  951.     DCC_list    *Client;
  952.     char    *PortName;
  953.     struct    in_addr    address;
  954.     struct    hostent    *hp;
  955.     int    lastlog_level;
  956.  
  957.     lastlog_level = set_lastlog_msg_level(LOG_DCC);
  958.     if ((address.s_addr = inet_addr(host)) == -1)
  959.     {
  960.         hp = gethostbyname(host);
  961.         if (!hp)
  962.         {
  963.             put_it("%s", convert_output_format("$G %RDCC%n Unknown host: $0-", "%s", host));
  964.             set_lastlog_msg_level(lastlog_level);
  965.             return m_strdup(empty_string);
  966.         }
  967.         memcpy(&address, hp->h_addr, sizeof(address));
  968.     }
  969.     Client = dcc_searchlist(host, ltoa(port), DCC_RAW, 1, NULL, NULL, -1);
  970.     if (Client->flags & DCC_ACTIVE)
  971.     {
  972.         put_it("%s", convert_output_format("$G %RDCC%n A previous DCC raw to $0 on $1 exists", "%s %d", host, port));
  973.         set_lastlog_msg_level(lastlog_level);
  974.         return m_strdup(empty_string);
  975.     }
  976.     /* Sorry. The missing 'htons' call here broke $connect() */
  977.     Client->remport = htons(port);
  978.     memcpy((char *) &Client->remote, (char *) &address, sizeof(address));
  979.     Client->flags = DCC_OFFER | DCC_RAW;
  980.     if (!dcc_open(Client))
  981.         return m_strdup(empty_string);
  982.     PortName = ltoa(Client->read);
  983.     Client->user = m_strdup(PortName);
  984.     if (do_hook(DCC_RAW_LIST, "%s %s E %d", PortName, host, port))
  985.             if (do_hook(DCC_CONNECT_LIST,"%s RAW %s %d",PortName, host, port))
  986.             put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  987.                 "%s %s %s %s %s %d", update_clock(GET_TIME), "RAW", host, 
  988.                 Client->userhost?Client->userhost:"u@h", PortName, port));
  989.     (void) set_lastlog_msg_level(lastlog_level);
  990.     return m_strdup(ltoa(Client->read));
  991. }
  992.  
  993. void real_dcc_filesend(char *filename, char *real_file, char *user, char *passwd, int type, int portnum)
  994. {
  995.     DCC_list *Client;
  996.     struct    stat    stat_buf;
  997.     char *nick = NULL;
  998.     
  999.     stat_file(filename, &stat_buf);
  1000. #ifdef S_IFDIR
  1001.     if (stat_buf.st_mode & S_IFDIR)
  1002.     {
  1003.         put_it("%s", convert_output_format("$G %RDCC%n Cannot send a directory", NULL, NULL));
  1004.         return;
  1005.     }
  1006. #endif
  1007. #if !defined(WINNT) && !defined(__EMX__)
  1008.     if (!strncmp(filename, "/etc/", 5))
  1009.     {
  1010.         put_it("%s", convert_output_format("$G %RDCC%n Send request for /etc rejected", NULL, NULL));
  1011.         return;
  1012.     }
  1013. #endif
  1014.     filesize = stat_buf.st_size;
  1015.     while ((nick = next_in_comma_list(user, &user)))
  1016.     {
  1017.         if (!nick || !*nick)
  1018.             break;
  1019.         Client = dcc_searchlist(filename, nick, type, 1, real_file, NULL, -1);
  1020.         filesize = 0;
  1021.         if (!(Client->flags & DCC_ACTIVE) && !(Client->flags & DCC_WAIT))
  1022.         {
  1023.             Client->flags |= DCC_TWOCLIENTS;
  1024.             Client->remport = portnum;
  1025.             dcc_open(Client);
  1026.         } else
  1027.             put_it("%s", convert_output_format("$G %RDCC%n A previous DCC send:$0 to $1 exists", "%s %s", filename, nick));
  1028.     }
  1029. }
  1030.  
  1031. void dcc_resend(char *command, char *args)
  1032. {
  1033.     char    *user = NULL;
  1034.     char    *filename = NULL,
  1035.         *fullname = NULL;
  1036.     char    *passwd = NULL;
  1037.     char    *FileBuf = NULL;
  1038.     int    portnum = 0;
  1039.     int    tdcc = 0;
  1040.     
  1041.     if (!(user = next_arg(args, &args)) || !(filename = next_arg(args, &args)))
  1042.     {
  1043.         put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname and a filename for DCC resend", NULL, NULL));
  1044.         return;
  1045.     }
  1046. #if defined(WINNT) || defined(__EMX__)
  1047.     if (*filename == '\\' || *filename == '/')
  1048. #else
  1049.     if (*filename == '/')
  1050. #endif
  1051.     {
  1052.         malloc_strcpy(&FileBuf, filename);
  1053.     }
  1054.     else if (*filename == '~')
  1055.     {
  1056.         if (!(fullname = expand_twiddle(filename)))
  1057.         {
  1058.             put_it("%s", convert_output_format("$G %RDCC%n Unable to expand: $0", "%s", filename));
  1059.             return;
  1060.         }
  1061.         malloc_strcpy(&FileBuf, fullname);
  1062.         new_free(&fullname);
  1063.     }
  1064.     else
  1065.     {
  1066.         char current_dir[BIG_BUFFER_SIZE+1];
  1067.         *current_dir = 0;
  1068.         getcwd(current_dir, BIG_BUFFER_SIZE - strlen(filename) - 4);
  1069.         malloc_sprintf(&FileBuf, "%s/%s", current_dir, filename); 
  1070.     }
  1071.  
  1072.     if (access(FileBuf, R_OK))
  1073.     {
  1074.         put_it("%s", convert_output_format("$G %RDCC%n Cannot access: $0", "%s", FileBuf));
  1075.         new_free(&FileBuf);
  1076.         return;
  1077.     }
  1078.     if (command)
  1079.         tdcc = !my_stricmp(command, "TRESEND");    
  1080.  
  1081.     while (args && *args)
  1082.     {
  1083.         char *argument = next_arg(args, &args);
  1084.         if (argument && strlen(argument) >=2)
  1085.         {
  1086.             if (*argument == '-' || *(argument+1) == 'e')
  1087.                 passwd = next_arg(args, &args);
  1088.             else if (*argument == '-' || *(argument+1) == 'p')
  1089.             {
  1090.                 char *v = next_arg(args, &args);
  1091.                 portnum = (v) ? my_atol(v) : 0;
  1092.             }
  1093.         }
  1094.     }
  1095.  
  1096.     real_dcc_filesend(FileBuf,filename, user, passwd, tdcc?DCC_TDCC|DCC_RESENDOFFER:DCC_RESENDOFFER, portnum);
  1097.     new_free(&FileBuf);
  1098. }
  1099.  
  1100. void        dcc_filesend (char *command, char *args)
  1101. {
  1102.     char    *user = NULL;
  1103.     char    *filename = NULL,
  1104.         *fullname = NULL;
  1105.     char    FileBuf[BIG_BUFFER_SIZE + 1];
  1106.     char    *passwd = NULL;
  1107.     int    portnum = 0;
  1108.     int    tdcc = 0;        
  1109.  
  1110.     *FileBuf = 0;
  1111.     if (!(user = next_arg(args, &args)) || !(filename = next_arg(args, &args)))
  1112.     {
  1113.         put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname and a filename for DCC send", NULL, NULL));
  1114.         return;
  1115.     }
  1116.     if (command)
  1117.         tdcc = !my_stricmp(command, "TSEND");    
  1118.  
  1119. #if defined(WINNT) || defined(__EMX__)
  1120.     if (*filename == '\\' || *filename == '/')
  1121. #else
  1122.     if (*filename == '/')
  1123. #endif
  1124.         strcpy(FileBuf, filename);
  1125.  
  1126.     else if (*filename == '~')
  1127.     {
  1128.         if (0 == (fullname = expand_twiddle(filename)))
  1129.         {
  1130.             put_it("%s", convert_output_format("$G %RDCC%n Unable to expand: $0", "%s", filename));
  1131.             return;
  1132.         }
  1133.         strcpy(FileBuf, fullname);
  1134.         new_free(&fullname);
  1135.     }
  1136.     else
  1137.     {
  1138.         getcwd(FileBuf, BIG_BUFFER_SIZE);
  1139.         strcat(FileBuf, "/");
  1140.         strcat(FileBuf, filename);
  1141.     }
  1142.  
  1143.     while (args && *args)
  1144.     {
  1145.         char *argument = next_arg(args, &args);
  1146.         if (argument && strlen(argument) >= 2)
  1147.         {
  1148.             if (*argument == '-' && *(argument+1) == 'e')
  1149.                 passwd = next_arg(args, &args);
  1150.             else if (*argument == '-' && *(argument+1) == 'p')
  1151.             {
  1152.                 char *v = next_arg(args, &args);
  1153.                 portnum = (v) ? my_atol(v) : 0;
  1154.             }
  1155.         }
  1156.     }
  1157.  
  1158. #if defined(WINNT) || defined(__EMX__)
  1159.     convert_unix(FileBuf);
  1160. #endif
  1161.     if (!strchr(FileBuf, '*') && access(FileBuf, R_OK))
  1162.     {
  1163.         put_it("%s", convert_output_format("$G %RDCC%n Cannot access: $0", "%s", FileBuf));
  1164.         return;
  1165.     } 
  1166.     else 
  1167.     if (strchr(FileBuf, '*'))
  1168.     {
  1169.         char *path = NULL;
  1170.         char *thefile;
  1171.         DIR *dp;
  1172.         struct dirent *dir;
  1173.         struct stat stbuf;
  1174.         char *filebuf = NULL;
  1175.         char *expand = NULL;
  1176.         int count = 0;
  1177.         malloc_strcpy(&path, FileBuf);
  1178.  
  1179.         if ((thefile = strrchr(path, '/')) != NULL)
  1180.             *thefile++ = '\0';
  1181.         else {
  1182.             malloc_strcpy(&path, "~");
  1183.             thefile = FileBuf;
  1184.         }
  1185.         expand = expand_twiddle(path);
  1186.         
  1187.         if ((dp = opendir(expand)) == NULL)
  1188.         {
  1189.             put_it("%s", convert_output_format("$G %RDCC%n Cannot access directory: $0", "%s", expand));
  1190.             new_free(&expand);
  1191.             new_free(&path);
  1192.             return;
  1193.         }
  1194.         
  1195.         while(1)
  1196.         {
  1197.             dir = readdir(dp);
  1198.             if (!dir) 
  1199.                 break;
  1200.             if (dir->d_ino == 0)
  1201.                 continue;
  1202.             if (!match(thefile, dir->d_name))
  1203.                 continue;
  1204.             malloc_sprintf(&filebuf, "%s/%s", expand, dir->d_name);
  1205.             stat(filebuf, &stbuf);
  1206.             if (S_ISDIR(stbuf.st_mode))
  1207.                 continue;
  1208.             count++;
  1209.             real_dcc_filesend(filebuf, dir->d_name, user, passwd, tdcc?DCC_TDCC|DCC_FILEOFFER:DCC_FILEOFFER, 0);
  1210.         }
  1211.         new_free(&filebuf);
  1212.         if (!dcc_quiet)
  1213.         {
  1214.             if (count)
  1215.                 put_it("%s", convert_output_format("$G %RDCC%n Sent DCC SEND request to $0 for files $1", "%s %s", user, FileBuf));
  1216.             else
  1217.                 put_it("%s", convert_output_format("$G %RDCC%n No Files found matching $0", "%s", FileBuf));
  1218.         }
  1219.         new_free(&path);
  1220.         new_free(&expand);
  1221.         return;
  1222.     }
  1223.     real_dcc_filesend(FileBuf, filename, user, passwd, tdcc?DCC_TDCC|DCC_FILEOFFER:DCC_FILEOFFER, portnum);
  1224. }
  1225.  
  1226. void multiget(char *usern, char *filen)
  1227. {
  1228.     DCC_list    *dccList;
  1229.     char        *newbuf = NULL;
  1230.     char         *expand = NULL;    
  1231.     char        *q = NULL;
  1232.     doing_multi = 1;
  1233.     if ((q = strchr(filen, ' ')))
  1234.         *q = 0;
  1235.     for (dccList = ClientList; dccList ; dccList = dccList->next)
  1236.         {
  1237.             if((match(dccList->description, filen) || match(filen, dccList->description))&& 
  1238.             !my_stricmp(usern, dccList->user) && 
  1239.             (dccList->flags & DCC_TYPES) == DCC_FILEREAD)
  1240.         {
  1241.             if (get_string_var(DCC_DLDIR_VAR)) 
  1242.             {
  1243.                 expand = expand_twiddle(get_string_var(DCC_DLDIR_VAR));
  1244.                 malloc_sprintf(&newbuf, "%s %s/%s", usern, expand, dccList->description);
  1245.             } else
  1246.                 malloc_sprintf(&newbuf, "%s %s", usern, dccList->description);
  1247.             if (!dcc_quiet)
  1248.                 put_it("%s", convert_output_format("$G %RDCC%n Attempting DCC get: $0", "%s", dccList->description));
  1249.             dcc_getfile(NULL, newbuf);
  1250.             new_free(&expand);
  1251.             new_free(&newbuf);
  1252.         }
  1253.     }
  1254.     doing_multi = 0;
  1255. }
  1256.  
  1257.  
  1258. static void dcc_getfile (char *command, char *args)
  1259. {
  1260.     char    *user;
  1261.     char    *nick;
  1262.     char    *filename = NULL;
  1263.     char    *tmp = NULL;
  1264.     DCC_list    *Client;
  1265.     char    *fullname = NULL;
  1266.     char    *passwd = NULL;
  1267.     char    *argument = NULL;
  1268.     int    tdcc = 0;
  1269.             
  1270. #ifdef PUBLIC_ACCESS
  1271.     bitchsay("This command has been disabled on a public access system");
  1272.     return;
  1273. #endif
  1274.     if (0 == (user = next_arg(args, &args)))
  1275.     {
  1276.         put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC get", NULL, NULL));
  1277.         return;
  1278.     }
  1279.     if (command)
  1280.         tdcc = !my_stricmp(command, "TGET");    
  1281.     if (args && *args)
  1282.     {
  1283.         if (args && strlen(args) >= 2)
  1284.         {
  1285.             if (*args != '-' && *(args+1) != 'e')
  1286.                 filename = next_arg(args, &args);
  1287.             else if (args && *args == '-' && *(args+1) == 'e')
  1288.             {
  1289.                 argument = next_arg(args, &args);
  1290.                 passwd = next_arg(args, &args);
  1291.             }
  1292.         }
  1293.     }
  1294.  
  1295. #if defined(WINNT) || defined(__EMX__)
  1296.     if (filename)
  1297.         convert_unix(filename);
  1298. #endif
  1299.     while ((nick = next_in_comma_list(user, &user)))
  1300.     {
  1301.         if (!nick || !*nick)
  1302.             break;
  1303.         
  1304.         if (!(Client = dcc_searchlist(filename, nick, DCC_FILEREAD, 0, NULL, NULL, 0)))
  1305.         {
  1306.             if (filename)
  1307.                 put_it("%s", convert_output_format("$G %RDCC%n No file ($0) offered in SEND mode by $1", "%s %s", filename, nick));
  1308.             else
  1309.                 put_it("%s", convert_output_format("$G %RDCC%n No file offered in SEND mode by $0", "%s", nick));
  1310.             continue;
  1311.         }
  1312.         if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  1313.         {
  1314.             put_it("%s", convert_output_format("$G %RDCC%n A previous DCC get:$0 to $0 exists", "%s %s", filename, nick));
  1315.             continue;
  1316.         }
  1317.         Client->flags |= DCC_TWOCLIENTS;
  1318.         Client->bytes_sent = Client->bytes_read = 0L;
  1319.  
  1320.         if (passwd)
  1321.             Client->encrypt = m_strdup(passwd);
  1322.  
  1323.         if (!dcc_open(Client))
  1324.             continue;
  1325.         if (get_string_var(DCC_DLDIR_VAR))
  1326.             malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), Client->description);
  1327.         else
  1328.             tmp = m_strdup(Client->description);
  1329.         if (!(fullname = expand_twiddle(tmp)))
  1330.             malloc_strcpy(&fullname, tmp);
  1331.  
  1332. #if defined(WINNT) || defined(__EMX__)
  1333.         if (-1 == (Client->file = open(fullname, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY/*, 0644*/)))
  1334. #else
  1335.         if (-1 == (Client->file = open(fullname, O_WRONLY | O_TRUNC | O_CREAT, 0644)))
  1336. #endif
  1337.         {
  1338.             put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0: $1-", "%s %s", fullname, errno?strerror(errno):"Unknown"));
  1339.             if (dcc_active_count) dcc_active_count--;
  1340.             Client->flags |= DCC_DELETE;
  1341.         }
  1342.         new_free(&fullname);
  1343.         new_free(&tmp);
  1344.     }
  1345. }
  1346.  
  1347.  
  1348. void dcc_regetfile(char *command, char *args)
  1349. {
  1350.     char    *user;
  1351.     char    *nick;
  1352.     char    *passwd = NULL;
  1353.     char    *tmp = NULL;
  1354.     char    *filename = NULL;
  1355.     DCC_list    *Client;
  1356.     char    *fullname = NULL;
  1357.     struct stat buf;
  1358.     int tdcc = 0;
  1359.     
  1360. #ifdef PUBLIC_ACCESS
  1361.     bitchsay("This command has been disabled on a public access system");
  1362.     return;
  1363. #endif
  1364.     if (0 == (user = next_arg(args, &args)))
  1365.     {
  1366.         put_it("%s", convert_output_format("$G %RDCC%n You must supply a nickname for DCC get", NULL, NULL));
  1367.         return;
  1368.     }
  1369.     if (command)
  1370.         tdcc = !my_stricmp(command, "TREGET");    
  1371.  
  1372.     while (args && *args)
  1373.     {
  1374.         if (args && strlen(args) >= 2)
  1375.         {
  1376.             if (!my_strnicmp(args, "-e", 2))
  1377.             {
  1378.                 next_arg(args, &args);
  1379.                 passwd = next_arg(args, &args);
  1380.             } 
  1381.             else
  1382.                 filename = next_arg(args, &args);
  1383.         }
  1384.     }
  1385.  
  1386. #if defined(WINNT) || defined(__EMX__)
  1387.     if (filename)
  1388.         convert_unix(filename);
  1389. #endif
  1390.     while ((nick = next_in_comma_list(user, &user)))
  1391.     {
  1392.         if (!nick || !*nick)
  1393.             break;
  1394.         if (!(Client = dcc_searchlist(filename, nick, DCC_REGETFILE, 0, NULL, NULL, 0)))
  1395.         {
  1396.             if (filename)
  1397.                 put_it("%s", convert_output_format("$G %RDCC%n No file ($0) offered in RESEND mode by $1", "%s %s", filename, nick));
  1398.             else
  1399.                 put_it("%s", convert_output_format("$G %RDCC%n No file offered in RESEND mode by $0", "%s", nick));
  1400.             continue;
  1401.         }
  1402.         if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  1403.         {
  1404.             put_it("%s", convert_output_format("$G %RDCC%n A previous DCC reget:$0 to $0 exists", "%s %s", filename, nick));
  1405.             continue;
  1406.         }
  1407.         Client->flags |= DCC_TWOCLIENTS;
  1408.         Client->bytes_sent = Client->bytes_read = 0L;
  1409.  
  1410.         if (get_string_var(DCC_DLDIR_VAR))
  1411.             malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), Client->description);
  1412.         else
  1413.             tmp = m_strdup(Client->description);
  1414.         if (!(fullname = expand_twiddle(tmp)))
  1415.             malloc_strcpy(&fullname, tmp);
  1416.  
  1417.         if (passwd)
  1418.             Client->encrypt = m_strdup(passwd);
  1419.  
  1420.         if (!dcc_open(Client))
  1421.             continue;
  1422. #if defined(WINNT) || defined(__EMX__)
  1423.         if (-1 == (Client->file = open(fullname, O_WRONLY | O_CREAT | O_BINARY/*, 0644*/)))
  1424. #else
  1425.         if (-1 == (Client->file = open(fullname, O_WRONLY | O_CREAT, 0644)))
  1426. #endif
  1427.         {
  1428.             put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0: $1-", "%s %s", Client->description, errno?strerror(errno):"Unknown"));
  1429.             Client->flags |= DCC_DELETE;
  1430.             if (dcc_active_count) dcc_active_count--;
  1431.             continue;
  1432.         }
  1433.  
  1434.         /* seek to the end of the file about to be resumed */
  1435.         lseek(Client->file, 0, SEEK_END);
  1436.  
  1437.         /* get the size of our file to be resumed */
  1438.         fstat(Client->file, &buf);
  1439.  
  1440.         Client->transfer_orders.packet_id = DCC_PACKETID;
  1441.         Client->transfer_orders.byteoffset = buf.st_size;
  1442.         Client->transfer_orders.byteorder = byteordertest();
  1443. #ifndef NON_BLOCKING_CONNECTS
  1444.         /* send a packet to the sender with transfer resume instructions */
  1445.         send(Client->read, (const char *)&(Client->transfer_orders), sizeof(struct transfer_struct), 0);
  1446. #endif
  1447.         new_free(&fullname);
  1448.         new_free(&tmp);
  1449.     }
  1450. }
  1451.  
  1452. extern void    register_dcc_offer (char *user, char *type, char *description, char *address, char *port, char *size, char *extra, char *userhost)
  1453. {
  1454.     DCC_list *    Client;
  1455.     int        CType;
  1456.     char *        c = NULL;
  1457.     u_long        TempLong;
  1458.     unsigned    TempInt;
  1459.     int        do_auto = 0;    /* used in dcc chat collisions */
  1460.     int        do_autog = 1;
  1461.     long        packets = 0;
  1462.         
  1463. #if defined(WINNT) || defined(__EMX__)
  1464.     if ( (c = strrchr(description, '/')) || (c = strrchr(description, '\\')))
  1465. #else
  1466.     if ((c = strrchr(description, '/')))
  1467. #endif
  1468.         description = c + 1;
  1469.     if ('.' == *description)
  1470.         *description = '_';
  1471.  
  1472.     message_from(NULL, LOG_DCC);
  1473.     if (size && *size)
  1474.     {
  1475.         filesize = my_atol(size);
  1476.         packets = filesize / dccBlockSize() + 1;
  1477.     }
  1478.     else
  1479.         packets = filesize = 0;
  1480.  
  1481.     if (!my_stricmp(type, "CHAT"))
  1482.         CType = DCC_CHAT;
  1483.     else if (!my_stricmp(type, "BOT"))
  1484.         CType = DCC_BOTMODE;
  1485.     else if (!my_stricmp(type, "SEND"))
  1486.         CType = DCC_FILEREAD;
  1487.     else if (!my_stricmp(type, "RESEND"))
  1488.         CType = DCC_REGETFILE;
  1489.     else if (!my_stricmp(type, "TRESEND"))
  1490.         CType = DCC_TDCC|DCC_REGETFILE;
  1491.     else if (!my_stricmp(type, "TSEND"))
  1492.         CType = DCC_TDCC|DCC_FILEREAD;
  1493. #ifdef FTP_XMIT
  1494.     else if (!my_stricmp(type, "XMIT"))
  1495.     {
  1496.         dcc_xmitget(user, description, address, port);
  1497.         return;
  1498.     }
  1499. #endif
  1500. #ifdef MIRC_BROKEN_DCC_RESUME
  1501.     else if (!my_stricmp(type, "RESUME"))
  1502.     {
  1503.         /* 
  1504.          * Dont be deceieved by the arguments we're passing it.
  1505.          * The arguments are "out of order" because MIRC doesnt
  1506.          * send them in the traditional order.  Ugh.
  1507.          */
  1508.         dcc_getfile_resume_demanded(user, description, address, port);
  1509.         return;
  1510.     }
  1511.     else if (!my_stricmp(type, "ACCEPT"))
  1512.     {
  1513.         /*
  1514.          * See the comment above.
  1515.          */
  1516.         dcc_getfile_resume_start (user, description, address, port);
  1517.         return;
  1518.     }
  1519. #endif
  1520.         else
  1521.         {
  1522.         put_it("%s", convert_output_format("$G %RDCC%n Unknown DCC $0 ($1) recieved from $2", "%s %s %s", type, description, user));
  1523.         message_from(NULL, LOG_CRAP);
  1524.                 return;
  1525.         }
  1526.  
  1527.     Client = dcc_searchlist(description, user, CType, 1, NULL, NULL, -1);
  1528.     filesize = 0;
  1529.  
  1530.     if (extra && *extra)
  1531.         Client->cksum = m_strdup(extra);
  1532.  
  1533.     if (Client->flags & DCC_WAIT)
  1534.     {
  1535.         Client->flags |= DCC_DELETE;
  1536.         if (DCC_CHAT == CType)
  1537.         {
  1538.             Client = dcc_searchlist(description, user, CType, 1, NULL, NULL, -1);
  1539.             do_auto = 1;
  1540.         }
  1541.         else
  1542.         {
  1543.             
  1544.             put_it("%s", convert_output_format("$G %RDCC%n $0 collision for $1:$2", "%s %s %s", type, user, description));
  1545.             send_ctcp(CTCP_NOTICE, user, CTCP_DCC, "DCC %s collision occured while connecting to %s (%s)", type, nickname, description);
  1546.             message_from(NULL, LOG_CRAP);
  1547.             return;
  1548.         }
  1549.     }
  1550.     if (Client->flags & DCC_ACTIVE)
  1551.     {
  1552.         put_it("%s", convert_output_format("$G %RDCC%n Recieved DCC $0 request from $1 while previous session active", "%s %s", type, user));
  1553.         message_from(NULL, LOG_CRAP);
  1554.         return;
  1555.     }
  1556.     Client->flags |= DCC_OFFER;
  1557.  
  1558.     TempLong = strtoul(address, NULL, 10);
  1559.     Client->remote.s_addr = htonl(TempLong);
  1560.     TempInt = (unsigned) strtoul(port, NULL, 10);
  1561.     Client->remport = htons(TempInt);
  1562.  
  1563.     if (TempInt < 1024)
  1564.     {
  1565.         put_it("%s", convert_output_format("$G %RDCC%n $0 ($1) request from $2 rejected", "%s %s %s", type, description, user));
  1566.         Client->flags |= DCC_DELETE;
  1567.         message_from(NULL, LOG_CRAP);
  1568.         return;
  1569.     }
  1570.     if (userhost)
  1571.         Client->userhost = m_strdup(userhost);
  1572. #ifdef HACKED_DCC_WARNING
  1573.     /* This right here compares the hostname from the userhost stamped
  1574.      * on the incoming privmsg to the address stamped in the handshake.
  1575.      * We do not automatically reject any discrepencies, but warn the
  1576.      * user instead to be cautious.
  1577.      */
  1578.     {
  1579.         char tmpbuf[128];
  1580.         char *fromhost;
  1581.         u_32int_t compare, compare2;
  1582.         u_32int_t compare3, compare4;
  1583.         struct hostent *hostent_fromhost;
  1584.  
  1585.         strncpy(tmpbuf, FromUserHost, 127);
  1586.         fromhost = strchr(tmpbuf, '@');
  1587.         fromhost++;
  1588.         alarm(1);    /* dont block too long... */
  1589.         hostent_fromhost = gethostbyname(fromhost);
  1590.         alarm(0);
  1591.         if (!hostent_fromhost)
  1592.         {
  1593.             yell("Incoming handshake has an address [%s] that could not be figured out!", fromhost);
  1594.             yell("Please use caution in deciding whether to accept it or not");
  1595.         }
  1596.         else
  1597.         {
  1598.             compare = *((u_32int_t *)hostent_fromhost->h_addr_list[0]);
  1599.             compare2 = inet_addr(fromhost);
  1600.             compare3 = htonl(0x00000000);
  1601.             compare4 = htonl(0xffffffff);
  1602.             if (((compare != Client->remote.s_addr) &&
  1603.                 (compare2 != Client->remote.s_addr)))
  1604.             {
  1605.                 say("WARNING: Fake dcc handshake detected! [%lx]",Client->remote.s_addr);
  1606.                 say("Unless you know where this dcc request is coming from");
  1607.                 say("It is recommended you ignore it!");
  1608.                 do_auto = do_autog = 0;
  1609.             }
  1610.             if (compare3 == Client->remote.s_addr || compare4 == Client->remote.s_addr)
  1611.             {
  1612.                 yell("WARNING: Fake dcc handshake detected! [%lx]",(unsigned long)Client->remote.s_addr);
  1613.                 Client->flags = DCC_DELETE;
  1614.                 message_from(NULL, LOG_CRAP);
  1615.                 return;
  1616.             }
  1617. #if 0            
  1618. /* this doesn't quite work properly. a check for DCC_CHAT would be appropriate */
  1619.             if (Client->filesize < 1)
  1620.             {
  1621.                 yell("Danger, Will Robinson!  Null-file detected!");
  1622.                 yell("It is highly recommended you ignore this file.");
  1623.                 return;
  1624.             }
  1625. #endif
  1626.         }
  1627.     }
  1628. #endif
  1629.     if ((u_long) 0 == TempLong || 0 == Client->remport)
  1630.     {
  1631.         yell("DCC handshake from %s ignored becuase it had an null port or address", user);
  1632.         Client->flags = DCC_DELETE;
  1633.         message_from(NULL, LOG_CRAP);
  1634.         return;
  1635.     }
  1636.     if (((Client->flags & DCC_TYPES) == DCC_FILEREAD) && ((Client->flags & DCC_TYPES) != DCC_REGETFILE))
  1637.     {
  1638.         struct stat statit;
  1639.         char *tmp = NULL, *p;
  1640.         malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), Client->description);
  1641.         p = expand_twiddle(tmp);
  1642.         if ( !dcc_overwrite_var && get_int_var(DCC_AUTOGET_VAR) && ((do_autog = stat(p, &statit)) == 0) )
  1643.         {
  1644.             if (!get_int_var(DCC_AUTORENAME_VAR))
  1645.             /* the file exists. warning is generated */
  1646.                 put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 exists: use /DCC rename if you dont want to overwrite", "%s", p));
  1647.             else
  1648.             {
  1649.                 rename_file(p, &Client->description);
  1650.                 put_it("%s", convert_output_format("$G %RDCC%n Warning: File $0 renamed: $1", "%s %s", p, Client->description));
  1651.                 description = Client->description;
  1652.                 do_autog = 1;
  1653.             }
  1654.         }
  1655.         new_free(&tmp); new_free(&p);
  1656.     }
  1657.       if (do_auto)
  1658.       {
  1659.                 if (do_hook(DCC_CONNECT_LIST,"%s CHAT %s",user, "already requested connecting"))
  1660.             put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  1661.                 "%s %s %s %s %s %d", update_clock(GET_TIME), "CHAT", user, 
  1662.                 " ", "already requested connecting...", 0));
  1663.           dcc_chat(NULL, user);
  1664.       }
  1665.         else if (do_hook(DCC_REQUEST_LIST,"%s %s %s %d",user, type, description, Client->filesize))
  1666.     {
  1667.         if (!dcc_quiet)
  1668.         {
  1669.     
  1670.             char buf[40];
  1671.             sprintf(buf, "%2.4g",_GMKv(Client->filesize));
  1672.             if (Client->filesize)
  1673.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET), 
  1674.                     "%s %s %s %s %s %s %d %s %s", 
  1675.                     update_clock(GET_TIME),type,description,user, FromUserHost,
  1676.                     inet_ntoa(Client->remote),ntohs(Client->remport), 
  1677.                     _GMKs(Client->filesize), buf));
  1678.             else
  1679.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_REQUEST_FSET), 
  1680.                     "%s %s %s %s %s %s %d", update_clock(GET_TIME),type,description,
  1681.                     user, FromUserHost,inet_ntoa(Client->remote),ntohs(Client->remport)));
  1682.             
  1683.         }
  1684.         if (CType == DCC_CHAT)
  1685.         {
  1686.             if (get_int_var(BOT_MODE_VAR) && find_user_level(Client->user, FromUserHost, "*"))
  1687.             {
  1688.                 dcc_open(Client);
  1689.                 message_from(NULL, LOG_CRAP);
  1690.                 return;
  1691.             }
  1692.             else
  1693.             {
  1694.                 bitchsay("Type /chat to answer or /nochat to close");
  1695.                 last_chat_req = m_strdup(user);
  1696.             }
  1697.         }
  1698.     }
  1699.  
  1700.     if (CType == DCC_BOTMODE && get_string_var(BOT_PASSWD_VAR))
  1701.     {
  1702.         if (((Client->encrypt && !strcmp(get_string_var(BOT_PASSWD_VAR), Client->encrypt))) || !Client->encrypt)
  1703.             dcc_open(Client);
  1704.         message_from(NULL, LOG_CRAP);
  1705.         return;
  1706.     }
  1707.     if ((get_int_var(DCC_AUTOGET_VAR) || (!get_int_var(DCC_AUTOGET_VAR) && find_name_in_genericlist(user, dcc_no_flood, DCC_HASHSIZE, 0))) && 
  1708.         (Client->filesize/1024 < get_int_var(DCC_MAX_AUTOGET_SIZE_VAR))
  1709.         && ((CType & DCC_TYPES) == DCC_FILEREAD || (CType & DCC_TYPES) == DCC_REGETFILE))
  1710.     {
  1711.         char *thebuf = NULL;
  1712.         if (!Client->filesize)
  1713.         {
  1714.             put_it("%s", convert_output_format("$G %RDCC Caution Filesize is 0!! No Autoget", NULL, NULL));
  1715.             message_from(NULL, LOG_CRAP);
  1716.             return;
  1717.         }
  1718.         malloc_sprintf(&thebuf, "%s %s", user, description);
  1719.         if ((((CType & DCC_TYPES) == DCC_REGETFILE) || do_autog) && !dcc_quiet)
  1720.         {
  1721.             char *prompt;
  1722.             prompt = m_strdup(convert_output_format(get_string_var(CDCC_PROMPT_VAR), NULL, NULL));
  1723.             put_it("%s", convert_output_format("$3- Auto-$0ting file %C$1%n from %K[%C$2%K]", "%s %s %s %s", ((CType & DCC_TYPES)== DCC_REGETFILE) ? (CType & DCC_TDCC?"treget":"reget"):(CType & DCC_TDCC?"tget":"get"), description, user, prompt));
  1724.             new_free(&prompt);
  1725.         }
  1726.         if (do_autog)
  1727.         {
  1728.             if ((CType & DCC_TYPES) == DCC_REGETFILE)
  1729.                 dcc_regetfile(type, thebuf);
  1730.             else 
  1731.                 dcc_getfile(type, thebuf);
  1732.         }
  1733.         new_free(&thebuf);
  1734.     }
  1735.     message_from(NULL, LOG_CRAP);
  1736.     return;
  1737. }
  1738.  
  1739. static void process_incoming_chat (DCC_list *Client)
  1740. {
  1741.     struct    sockaddr_in    remaddr;
  1742.     int    sra;
  1743.     char    tmp[MAX_DCC_BLOCK_SIZE*4 + 1];
  1744.     char    tmp2[MAX_DCC_BLOCK_SIZE*4 + 1];
  1745.     char    *s = NULL, *bufptr = NULL;
  1746.     char    *buf = NULL;
  1747.     u_32int_t    bytesread;
  1748.     int    type = Client->flags & DCC_TYPES;
  1749.     
  1750.     if (Client->flags & DCC_WAIT)
  1751.     {
  1752.         sra = sizeof(struct sockaddr_in);
  1753.         Client->write = accept(Client->read, (struct sockaddr *) &remaddr, &sra);
  1754.         Client->read = new_close(Client->read);
  1755.         if ((Client->read = Client->write) > 0)
  1756.             new_open(Client->read);
  1757.         else
  1758.         {
  1759.             put_it("%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
  1760.             Client->flags |= DCC_DELETE;
  1761.             return;
  1762.         }
  1763.         Client->flags &= ~DCC_WAIT;
  1764.         Client->flags |= DCC_ACTIVE;
  1765.                 if (do_hook(DCC_CONNECT_LIST, "%s CHAT %s %d", Client->user,
  1766.                          inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port)))
  1767.             put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  1768.                 "%s %s %s %s %s %d", update_clock(GET_TIME),
  1769.                 type == DCC_BOTMODE ? "BOT":"CHAT", 
  1770.                 Client->user, Client->userhost?Client->userhost:"u@h",
  1771.                 inet_ntoa(remaddr.sin_addr),ntohs(remaddr.sin_port)));
  1772.         if ((type == DCC_BOTMODE) && Client->encrypt)
  1773.             new_free(&Client->encrypt);
  1774.         get_time(&Client->starttime);
  1775.         return;
  1776.     }
  1777.         s = Client->buffer;
  1778.         bufptr = tmp;
  1779.  
  1780.     bytesread = dgets(bufptr, Client->read, 1);
  1781.     switch (bytesread)
  1782.     {
  1783.         case -1:
  1784.         {
  1785.             char *real_tmp = ((dgets_errno == -1) ? "Remote End Closed Connection" : strerror(dgets_errno));
  1786.                     if (do_hook(DCC_LOST_LIST, "%s CHAT %s", Client->user, real_tmp))
  1787.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), 
  1788.                     "%s %s %s %s", update_clock(GET_TIME), 
  1789.                     type == DCC_BOTMODE? "BOT":"CHAT", 
  1790.                     Client->user, real_tmp));
  1791.             Client->flags |= DCC_DELETE;
  1792.             return;
  1793.         }
  1794.         case 0:
  1795.             break;
  1796.         default:
  1797.         {
  1798.             char userhost[BIG_BUFFER_SIZE+1];
  1799.             char equal_nickname[NICKNAME_LEN+4];
  1800.         
  1801.             new_free(&Client->buffer);
  1802.             if (tmp[strlen(tmp) - 1] == '\n')
  1803.                 tmp[strlen(tmp) - 1] = 0;
  1804.             my_decrypt(tmp, strlen(tmp), Client->encrypt);
  1805.             Client->bytes_read += bytesread;
  1806.             message_from(Client->user, LOG_DCC);
  1807.             malloc_strcpy(&buf, tmp);
  1808.  
  1809. #undef CTCP_REPLY
  1810. #define CTCP_MESSAGE "CTCP_MESSAGE "
  1811. #define CTCP_MESSAGE_LEN strlen(CTCP_MESSAGE)
  1812. #define CTCP_REPLY "CTCP_REPLY "
  1813. #define CTCP_REPLY_LEN strlen(CTCP_REPLY)
  1814.  
  1815. #ifndef BITCHX_LITE
  1816.             if ((Client->flags & DCC_TYPES) == DCC_BOTMODE)
  1817.             {
  1818.                 if (Client->read > -1)
  1819.                     handle_dcc_bot(Client->read, buf);
  1820.             }
  1821.             else 
  1822.             {
  1823.                 if (*buf == '.')
  1824.                 {
  1825.                     if (!check_tcl_dcc(buf+1, Client->user, Client->userhost?Client->userhost:"", Client->read, Client))
  1826.                         dcc_printf(Client->write, "Unknown command\n");
  1827.                 }
  1828.                 else 
  1829. #endif
  1830.                 {
  1831.                     if (!Client->userhost)
  1832.                     {
  1833.                         strcpy(userhost, "Unknown@");
  1834.                         strcat(userhost, inet_ntoa(remaddr.sin_addr));
  1835.                         FromUserHost = userhost;
  1836.                     }
  1837.                     else
  1838.                         FromUserHost = Client->userhost;
  1839.  
  1840.                     strncpy(equal_nickname, "=", NICKNAME_LEN);
  1841.                     strncat(equal_nickname, Client->user, NICKNAME_LEN);
  1842.                     if (!strncmp(tmp, CTCP_MESSAGE, CTCP_MESSAGE_LEN))
  1843.                     {
  1844.                         strcpy(tmp2, tmp);
  1845.                         strcpy(tmp, do_ctcp(equal_nickname, get_server_nickname(from_server), stripansicodes(tmp2 + CTCP_MESSAGE_LEN)));
  1846.                         if (!*tmp)
  1847.                             break;
  1848.                     }
  1849.                     else if (!strncmp(tmp, CTCP_REPLY, CTCP_REPLY_LEN) || *tmp == CTCP_DELIM_CHAR)
  1850.                     {
  1851.                         strcpy(tmp2, tmp);
  1852.                         strcpy(tmp, do_notice_ctcp(equal_nickname, get_server_nickname(from_server), stripansicodes(tmp2  + ((*tmp2 == CTCP_DELIM_CHAR) ? 0 : CTCP_REPLY_LEN))));
  1853.                         if (!*tmp)
  1854.                             break;
  1855.                     }
  1856. #ifndef BITCHX_LITE
  1857.                     else if (Client->in_dcc_chat)
  1858.                     {
  1859.                         handle_tcl_chan(Client->read, Client->user, Client->userhost, tmp);
  1860.                         break;
  1861.                     }
  1862. #endif
  1863.                     if (do_hook(DCC_CHAT_LIST, "%s %s", Client->user, tmp))
  1864.                     {
  1865.                         addtabkey(equal_nickname, "msg", 0);
  1866.                         put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CHAT_FSET), 
  1867.                             "%s %s %s %s", update_clock(GET_TIME), Client->user, Client->userhost?Client->userhost:"u@h", tmp));
  1868.                         add_last_type(&last_dcc[0], MAX_LAST_MSG, Client->user, NULL, FromUserHost, tmp);
  1869.                     }
  1870.                     FromUserHost = empty_string;
  1871.                 }
  1872. #ifndef BITCHX_LITE
  1873.             }
  1874. #endif
  1875.         }
  1876.     }
  1877.     message_from(NULL, LOG_CRAP);
  1878.     new_free(&buf);
  1879. }
  1880.  
  1881. static    void        process_incoming_listen (DCC_list *Client)
  1882. {
  1883.     struct    sockaddr_in    remaddr;
  1884.     int    sra;
  1885.     char    FdName[10];
  1886.     DCC_list    *NewClient;
  1887.     int    new_socket;
  1888.     struct    hostent    *hp;
  1889. #if defined(__linux__) || defined(__sgi)
  1890.     const char    *Name;
  1891. #else
  1892.     char    *Name;
  1893. #endif
  1894.  
  1895.     sra = sizeof(struct sockaddr_in);
  1896.     new_socket = accept(Client->read, (struct sockaddr *) &remaddr, &sra);
  1897.     if (new_socket < 0)
  1898.     {
  1899.         put_it("%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
  1900.         return;
  1901.     }
  1902.     if (0 != (hp = gethostbyaddr((char *)&remaddr.sin_addr,
  1903.         sizeof(remaddr.sin_addr), remaddr.sin_family)))
  1904.         Name = hp->h_name;
  1905.     else
  1906.         Name = inet_ntoa(remaddr.sin_addr);
  1907.     sprintf(FdName, "%d", new_socket);
  1908.     NewClient = dcc_searchlist((char *)Name, FdName, DCC_RAW, 1, NULL, NULL, 0);
  1909.  
  1910.     get_time(&NewClient->starttime);
  1911.  
  1912.     NewClient->read = NewClient->write = new_socket;
  1913.     new_open(NewClient->read);
  1914.  
  1915.     NewClient->remote = remaddr.sin_addr;
  1916.     NewClient->remport = remaddr.sin_port;
  1917.     NewClient->flags |= DCC_ACTIVE;
  1918.     NewClient->bytes_read = NewClient->bytes_sent = 0L;
  1919.     if (do_hook(DCC_RAW_LIST, "%s %s N %d", NewClient->user,
  1920.                         NewClient->description,
  1921.                         Client->write))
  1922.             if (do_hook(DCC_CONNECT_LIST,"%s RAW %s %d", NewClient->user,
  1923.                                                          NewClient->description,
  1924.                                                          Client->write))
  1925.             put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  1926.                 "%s %s %s %s %s %d", update_clock(GET_TIME), 
  1927.                 "RAW", NewClient->user, 
  1928.                 Client->userhost? Client->userhost:"u@h", 
  1929.                 NewClient->description, Client->write));
  1930. }
  1931.  
  1932. static    void        process_incoming_raw (DCC_list *Client)
  1933. {
  1934.     char    tmp[MAX_DCC_BLOCK_SIZE + 1];
  1935.     char     *s, *bufptr;
  1936.     u_32int_t bytesread;
  1937.     int    len =  0;
  1938.     
  1939.         s = Client->buffer;
  1940.         bufptr = tmp;
  1941.         if (s && *s)
  1942.         {
  1943.         len = strlen(s);
  1944.         if (len > MAX_DCC_BLOCK_SIZE - 1)
  1945.         {
  1946.             put_it("%s", convert_output_format("$G %RDCC raw buffer overrun. Data lost", NULL, NULL));
  1947.             new_free(&Client->buffer);
  1948.         }
  1949.         else
  1950.         { 
  1951.                     strncpy(tmp, s, len);
  1952.                     bufptr += len;
  1953.         }
  1954.         }
  1955.     switch(bytesread = dgets(bufptr, Client->read, 0))
  1956.     {
  1957.         case -1:
  1958.         {
  1959.             if (do_hook(DCC_RAW_LIST, "%s %s C", Client->user, Client->description))
  1960.                        if (do_hook(DCC_LOST_LIST,"%s RAW %s", Client->user, Client->description))
  1961.                     put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), "RAW", Client->user, Client->description));
  1962.             Client->flags |= DCC_DELETE;
  1963.             return;
  1964.         }
  1965.         case 0:
  1966.         default:
  1967.         {
  1968.             new_free(&Client->buffer);
  1969.             if (tmp[strlen(tmp)-1] == '\n')
  1970.                 tmp[strlen(tmp) - 1] = '\0';
  1971.             Client->bytes_read += bytesread;
  1972.             if (Client->dcc_handler)
  1973.                 (Client->dcc_handler)(Client, tmp);
  1974.             else
  1975.             {
  1976.                 if (do_hook(DCC_RAW_LIST, "%s %s D %s",    Client->user, Client->description, tmp))
  1977.                     say("Raw data on %s from %s: %s", Client->user, Client->description, tmp);
  1978.             }
  1979.             return;
  1980.         }
  1981.     }
  1982. }
  1983.  
  1984.  
  1985. /* Now that ive mucked this function up, i should go back and fix it. */
  1986. static void    process_outgoing_file (DCC_list *Client, int readwaiting)
  1987. {
  1988.     struct    sockaddr_in    remaddr;
  1989.     int            sra;
  1990.     char            tmp[MAX_DCC_BLOCK_SIZE+1];
  1991.     u_32int_t        bytesrecvd = 0;
  1992.     int            bytesread = 0;
  1993.     char            *Type;
  1994.     unsigned char         packet[BIG_BUFFER_SIZE/8];
  1995.     struct  transfer_struct *received;
  1996.     int            tdcc = 0;
  1997.         
  1998.     Type = dcc_types[Client->flags & DCC_TYPES];
  1999.     tdcc = Client->flags & DCC_TDCC;
  2000.     
  2001.     if (Client->flags & DCC_WAIT)
  2002.     {
  2003.         sra = sizeof(struct sockaddr_in);
  2004.         Client->write = accept(Client->read, (struct sockaddr *) &remaddr, &sra);
  2005.         if ((Client->flags & DCC_RESENDOFFER) == DCC_RESENDOFFER)
  2006.         {
  2007.             recv(Client->write, packet, sizeof(struct transfer_struct), 0);
  2008.             received = (struct transfer_struct *)packet;
  2009.             if (byteordertest() != received->byteorder)
  2010.             {
  2011.                 /* the packet sender orders bytes differently than us,
  2012.                  * reverse what they sent to get the right value 
  2013.                  */
  2014.                 Client->transfer_orders.packet_id = 
  2015.                     ((received->packet_id & 0x00ff) << 8) | 
  2016.                     ((received->packet_id & 0xff00) >> 8);
  2017.  
  2018.                  Client->transfer_orders.byteoffset = 
  2019.                     ((received->byteoffset & 0xff000000) >> 24) |
  2020.                     ((received->byteoffset & 0x00ff0000) >> 8)  |
  2021.                     ((received->byteoffset & 0x0000ff00) << 8)  |
  2022.                     ((received->byteoffset & 0x000000ff) << 24);
  2023.             }
  2024.             else
  2025.                 memcpy(&Client->transfer_orders,packet,sizeof(struct transfer_struct));
  2026.  
  2027.             if (Client->transfer_orders.packet_id != DCC_PACKETID)
  2028.                 put_it("%s", convert_output_format("$G %RDCC%n reget packet is invalid!!", NULL, NULL));
  2029.             else
  2030.                 put_it("%s", convert_output_format("$G %RDCC%n reget starting at $0", "%d", Client->transfer_orders.byteoffset));
  2031.         }
  2032.  
  2033.         Client->read = new_close(Client->read);
  2034.  
  2035.         if ((Client->read = Client->write) >= 0)
  2036.             new_open(Client->read);
  2037.         else
  2038.         {
  2039.             put_it("%s", convert_output_format("$G %RDCC error: accept() failed. punt!!", NULL, NULL));
  2040.  
  2041.             Client->flags |= DCC_DELETE;
  2042.             if (get_to_from(Type) != -1 && dcc_active_count)
  2043.                 dcc_active_count--;
  2044.             return;
  2045.         }
  2046. #if 0
  2047. #if defined(NON_BLOCKING_CONNECTS)
  2048.         if (get_int_var(DCC_FAST_VAR) || (Client->flags & DCC_TDCC))
  2049.             set_non_blocking(Client->write);
  2050. #endif
  2051. #endif
  2052.         Client->flags &= ~DCC_WAIT;
  2053.         Client->flags |= DCC_ACTIVE;
  2054.         Client->eof = 0;
  2055.         get_time(&Client->starttime);
  2056. #if defined(WINNT) || defined(__EMX__)
  2057.         if ((Client->file = open(Client->description, O_RDONLY | O_BINARY)) == -1)
  2058. #else
  2059.         if ((Client->file = open(Client->description, O_RDONLY)) == -1)
  2060. #endif
  2061.         {
  2062.             put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0: $1-", "%s %s", Client->description, errno ? strerror(errno) : "Unknown Host"));
  2063.             Client->read = new_close(Client->read);
  2064.             Client->write = new_close(Client->write);
  2065.             if (get_to_from(Type) != -1 && dcc_active_count)
  2066.                 dcc_active_count--;
  2067.             Client->flags |= DCC_DELETE;
  2068.             return;
  2069.         }
  2070.         if ((Client->flags & DCC_RESENDOFFER) == DCC_RESENDOFFER)        
  2071.         {
  2072.             lseek(Client->file, Client->transfer_orders.byteoffset, SEEK_SET);
  2073.             errno = 0;
  2074.             if (do_hook(DCC_CONNECT_LIST,"%s %s %s %d",Client->user, tdcc?"TRESEND":"SEND",
  2075.                 inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port)))
  2076.                 if (!dcc_quiet)
  2077.                     put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  2078.                         "%s %s %s %s %s %d %d", update_clock(GET_TIME), tdcc?"TRESEND":"RESEND", 
  2079.                         Client->user, Client->userhost?Client->userhost:"u@h", inet_ntoa(remaddr.sin_addr),
  2080.                         ntohs(remaddr.sin_port), Client->transfer_orders.byteoffset));
  2081.         }
  2082.         else
  2083.         {
  2084.             if (do_hook(DCC_CONNECT_LIST,"%s %s %s %d %s %d",Client->user, tdcc?"TSEND":"SEND", 
  2085.                 inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port), Client->description, Client->filesize))
  2086.                 if (!dcc_quiet)
  2087.                     put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_CONNECT_FSET), 
  2088.                         "%s %s %s %s %s %d %d", update_clock(GET_TIME), tdcc?"TSEND":"SEND", 
  2089.                         Client->user, Client->userhost?Client->userhost:"u@h", inet_ntoa(remaddr.sin_addr),
  2090.                         ntohs(remaddr.sin_port), Client->transfer_orders.byteoffset));
  2091.             if (Client->transfer_orders.byteoffset)
  2092.                 lseek(Client->file, Client->transfer_orders.byteoffset, SEEK_SET);
  2093.         }
  2094.     }
  2095.     else if (readwaiting)
  2096.     { 
  2097.         if (!(Client->flags & DCC_TDCC))
  2098.         {
  2099.             if (read(Client->read, (char *)&bytesrecvd, sizeof(u_32int_t)) < sizeof(u_32int_t))
  2100.             {
  2101.                             if (do_hook(DCC_LOST_LIST,"%s SEND %s CONNECTION LOST",
  2102.                                     Client->user, Client->description))
  2103.                     put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), "SEND", Client->user, Client->description));
  2104.                 if (get_to_from(Type) != -1 && dcc_active_count)
  2105.                     dcc_active_count--;
  2106.                 Client->flags |= DCC_DELETE;
  2107.                 dcc_update_stats(Client);
  2108.                 return;
  2109.             }
  2110.             else if (ntohl(bytesrecvd) != Client->bytes_sent)
  2111.                 return;
  2112.         }
  2113.         else
  2114.             return;
  2115. /* CDE do we just return here? */
  2116.     }
  2117.  
  2118.     if ((bytesread = read(Client->file, tmp, dccBlockSize())) > 0)
  2119.     {
  2120.         my_encrypt(tmp, bytesread, Client->encrypt);
  2121.         send(Client->write, tmp, bytesread, 0);
  2122. #if 0        
  2123.         if ((write(Client->write, tmp, bytesread)) == -1)
  2124.         {
  2125.             yell("outbound write failed");
  2126.             Client->flags |= DCC_DELETE;
  2127.             return;
  2128.         }
  2129. #endif
  2130.         Client->packets_transfer++;
  2131.         Client->bytes_sent += bytesread;
  2132.         update_transfer_buffer("");
  2133.         if (!(Client->packets_transfer % 20))
  2134.             update_all_status(current_window, NULL, 0);
  2135.     } 
  2136.     else if (!readwaiting)
  2137.     {
  2138.         if (!(Client->flags & DCC_TDCC))
  2139.             Client->eof = 1;
  2140.         else 
  2141.             DCC_close_filesend(Client, "TSEND");
  2142.     } else 
  2143.         DCC_close_filesend(Client, tdcc?"TSEND":"SEND");
  2144. }
  2145.  
  2146. static    void        process_incoming_file (DCC_list *Client)
  2147. {
  2148.     char        tmp[MAX_DCC_BLOCK_SIZE+1];
  2149.     u_32int_t    bytestemp;
  2150.     int        bytesread;
  2151.     char        *Type;
  2152.     int        tdcc = 0;
  2153.  
  2154.     tdcc = Client->flags & DCC_TDCC;    
  2155.     Type = dcc_types[Client->flags & DCC_TYPES];
  2156.  
  2157.     if ((bytesread = read(Client->read, tmp, MAX_DCC_BLOCK_SIZE)) <= 0)
  2158.     {
  2159.         if (Client->bytes_read + Client->transfer_orders.byteoffset < Client->filesize)
  2160.             put_it("%s", convert_output_format("$G %RDCC get to $0 lost: Remote peer closed connection", "%s", Client->user));
  2161.         DCC_close_filesend(Client, tdcc?"TGET":"GET");
  2162.     }
  2163.     else
  2164.     {
  2165.         my_decrypt(tmp, bytesread, Client->encrypt);
  2166.         if ((write(Client->file, tmp, bytesread)) == -1)
  2167.         {
  2168.             yell("write to local file failed");
  2169.             Client->flags |= DCC_DELETE;
  2170.             return;
  2171.         }
  2172.  
  2173.         Client->bytes_read += bytesread;
  2174.         if (!(Client->flags & DCC_TDCC))
  2175.         {
  2176.             bytestemp = htonl(Client->bytes_read);
  2177.             send(Client->write, (char *)&bytestemp, sizeof(u_32int_t), 0);
  2178. #if 0
  2179.             if ((write(Client->write, (char *)&bytestemp, sizeof(u_32int_t))) == -1)
  2180.             {
  2181.                 yell("write to remote failed");
  2182.                 Client->flags |= DCC_DELETE;
  2183.                 return;
  2184.             }
  2185. #endif
  2186.         }
  2187.         Client->packets_transfer++;
  2188.  
  2189. /* TAKE THIS OUT IF IT CAUSES PROBLEMS */
  2190.         if (Client->filesize) 
  2191.         {
  2192.             if (Client->bytes_read > Client->filesize)
  2193.             {
  2194.                 put_it("%s", convert_output_format("$G %RDCC%n Warning: incoming file is larger than the handshake said", NULL, NULL));
  2195.                 put_it("%s", convert_output_format("$G %RDCC%n Warning: GET: closing connection", NULL, NULL));
  2196.                 if (dcc_active_count)
  2197.                     dcc_active_count--;
  2198.                 Client->flags |= DCC_DELETE;
  2199.                 dcc_update_stats(Client);
  2200.                 update_all_status(current_window, NULL, 0);
  2201.                 return;
  2202.             } 
  2203.             else if (Client->bytes_read == Client->filesize)
  2204.             {
  2205.                 DCC_close_filesend(Client, tdcc?"TGET":"GET");
  2206.                 return;
  2207.             }
  2208.             update_transfer_buffer("");
  2209.             if (!(Client->packets_transfer % 20))
  2210.                 update_all_status(current_window, NULL, 0);
  2211.         }
  2212.     }
  2213. }
  2214.  
  2215. /* flag == 1 means show it.  flag == 0 used by redirect (and /ctcp) */
  2216.  
  2217. extern void    dcc_message_transmit (char *user, char *text, char *text_display, int type, int flag, char *cmd, int check_host)
  2218. {
  2219.     DCC_list    *Client;
  2220.     char    tmp[MAX_DCC_BLOCK_SIZE+1];
  2221.     int    lastlog_level;
  2222.     int    list = 0;
  2223.     int     len = 0;
  2224.     char    *host = NULL;
  2225.     char    thing = 0;
  2226.     *tmp = 0;
  2227.     switch(type)
  2228.     {
  2229.         case DCC_CHAT:
  2230.             thing = '=';
  2231.             host = "chat";
  2232.             list = SEND_DCC_CHAT_LIST;
  2233.             break;
  2234.         case DCC_RAW:
  2235.             if (check_host)
  2236.             {
  2237.                 if (!(host = next_arg(text, &text)))
  2238.                 {
  2239.                     put_it("%s", convert_output_format("$G %RDCC%n No host specified for DCC RAW", NULL, NULL));
  2240.                     return;
  2241.                 }
  2242.             }
  2243.             break;
  2244.     }
  2245.     if (!(Client = dcc_searchlist(host, user, type, 0, NULL, NULL, 1)) || !(Client->flags & DCC_ACTIVE))
  2246.     {
  2247.         put_it("%s", convert_output_format("$G %RDCC No active $0:$1 connection for $2", "%s %s %s", dcc_types[type], host?host:"(null)", user));
  2248.         return;
  2249.     }
  2250.     lastlog_level = set_lastlog_msg_level(LOG_DCC);
  2251.     message_from(Client->user, LOG_DCC);
  2252.  
  2253.     /*
  2254.      * Check for CTCPs... whee.
  2255.      */
  2256.     if (cmd && *text == CTCP_DELIM_CHAR)
  2257.     {
  2258.         if (!strcmp(cmd, "PRIVMSG"))
  2259.             strmcpy(tmp, "CTCP_MESSAGE ", dccBlockSize());
  2260.         else
  2261.             strmcpy(tmp, "CTCP_REPLY ", dccBlockSize());
  2262.     }
  2263.  
  2264.     strmcat(tmp, text, dccBlockSize()-3);
  2265.     strmcat(tmp, "\n", dccBlockSize()-2); 
  2266.  
  2267.     len = strlen(tmp);
  2268.     my_encrypt(tmp, len, Client->encrypt);
  2269.     write(Client->write, tmp, len);
  2270.     Client->bytes_sent += len;
  2271.  
  2272.     if (flag && type != DCC_RAW)
  2273.     {
  2274.         if (!my_strnicmp(tmp, ".chat", strlen(tmp)))
  2275.             Client->in_dcc_chat = 1;
  2276.         if (do_hook(list, "%s %s", Client->user, text_display ? text_display : text))
  2277.             put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_DCC_CHAT_FSET), "%c %s %s", thing, Client->user, text_display?text_display:text));
  2278.     }
  2279.     set_lastlog_msg_level(lastlog_level);
  2280.     message_from(NULL, LOG_CRAP);
  2281.     return;
  2282. }
  2283.  
  2284. extern void    dcc_chat_transmit (char *user, char *text, char *orig, char *type)
  2285. {
  2286.     dcc_message_transmit(user, text, orig, DCC_CHAT, 1, type, 0);
  2287. }
  2288.  
  2289. extern void    dcc_raw_transmit (char *user, char *text, char *type)
  2290. {
  2291.     dcc_message_transmit(user, text, NULL, DCC_RAW, 0, type, 0);
  2292. }
  2293.  
  2294. extern void    dcc_bot_transmit (char *user, char *text, char *type)
  2295. {
  2296.     dcc_message_transmit(user, text, NULL, DCC_BOTMODE, 0, type, 1);
  2297. }
  2298.  
  2299. extern void dcc_chat_transmit_quiet (char *user, char *text, char *type)
  2300. {
  2301.     dcc_message_transmit(user, text, NULL, DCC_CHAT, 0, type, 0);
  2302. }
  2303.  
  2304. extern void dcc_chat_crash_transmit (char *user, char *text)
  2305. {
  2306. char buffer[20000];
  2307.     DCC_list    *Client;
  2308.     char    *host = "chat";
  2309.  
  2310.     memset(buffer, ' ', 20000-10);
  2311.     buffer[20000-9] = '\n';
  2312.     buffer[20000-8] = '\0';    
  2313.     if (!(Client = dcc_searchlist(host, user, DCC_CHAT, 0, NULL, NULL, 1)) || !(Client->flags&DCC_ACTIVE))
  2314.     {
  2315.         put_it("%s", convert_output_format("$G %RDCC%n No active DCC $0:$1 connection for $2", "%s %s %s", dcc_types[DCC_CHAT], host?host:"(null)", user));
  2316.         return;
  2317.     }
  2318.     send(Client->write, buffer, strlen(buffer), 0);
  2319.     Client->bytes_sent += strlen(buffer);
  2320.     return;
  2321. }
  2322.  
  2323. static    void        dcc_send_raw (char *command, char *args)
  2324. {
  2325.     char    *name;
  2326.  
  2327.     if (!(name = next_arg(args, &args)))
  2328.     {
  2329.         put_it("%s", convert_output_format("$G %RDCC%n No name specified for DCC raw", NULL, NULL));
  2330.         return;
  2331.     }
  2332.     dcc_message_transmit(name, args, NULL, DCC_RAW, 1, NULL, 1);
  2333. }
  2334.  
  2335. /*
  2336.  * dcc_time: Given a time value, it returns a string that is in the
  2337.  * format of "hours:minutes:seconds month day year" .  Used by 
  2338.  * dcc_list() to show the start time.
  2339.  */
  2340. char *dcc_time (time_t time)
  2341. {
  2342.     struct    tm    *btime;
  2343.     char    *buf = NULL;
  2344.     static    char    *months[] = 
  2345.     {
  2346.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  2347.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  2348.     };
  2349.  
  2350.     btime = localtime(&time);
  2351.     if (time)
  2352.         malloc_sprintf(&buf, "%-2.2d:%-2.2d:%-2.2d %s %-2.2d %d", btime->tm_hour,
  2353.             btime->tm_min, btime->tm_sec, months[btime->tm_mon],
  2354.             btime->tm_mday, btime->tm_year + 1900);
  2355.     return buf;
  2356. }
  2357.  
  2358. static char *get_dcc_type (unsigned long flag)
  2359. {
  2360. static char ret[20];
  2361.     if (flag & DCC_TDCC)
  2362.     {
  2363.         switch(flag & DCC_TYPES)
  2364.         {
  2365.             case DCC_FILEOFFER:
  2366.                 strcpy(ret, "TSEND");
  2367.                 break;
  2368.             case DCC_FILEREAD:
  2369.                 strcpy(ret, "TGET");
  2370.                 break;
  2371.             case DCC_RESENDOFFER:
  2372.                 strcpy(ret, "TRESEND");
  2373.                 break;
  2374.             case DCC_REGETFILE:
  2375.                 strcpy(ret, "TREGET");
  2376.                 break;
  2377.         }
  2378.     }
  2379.     else
  2380.         strcpy(ret, dcc_types[flag & DCC_TYPES]);
  2381.     return ret;
  2382. }
  2383.  
  2384. extern void dcc_list (char *command, char *args)
  2385. {
  2386.     DCC_list    *Client;
  2387.     const char    *format =
  2388.             "%-5.5s%-3.3s %-9.9s %-8.8s %-20.20s %-8.8s %-8.8s %s";
  2389.     unsigned    flags;
  2390.     int count = 0;
  2391.     char *filename = NULL;
  2392.         
  2393.     for (Client = ClientList ; Client != NULL ; Client = Client->next)
  2394.     {
  2395.         char    completed[9];
  2396.         char    size[9];
  2397.         char    *stime = NULL;
  2398.  
  2399.         if (Client->filesize)
  2400.         {
  2401.             sprintf(completed, "%ld%%",(unsigned long) (Client->bytes_sent?Client->bytes_sent:Client->bytes_read) * 100 / Client->filesize);
  2402.             sprintf(size, "%ld", (unsigned long)Client->filesize);
  2403.         }
  2404.         else
  2405.         {
  2406.             sprintf(completed, "%ldK", (unsigned long) (Client->bytes_sent ? Client->bytes_sent : Client->bytes_read) / 1024);
  2407.             strcpy(size, empty_string);
  2408.         }
  2409.         stime = Client->starttime.tv_sec ? dcc_time(Client->starttime.tv_sec): "";
  2410.         flags = Client->flags;
  2411.  
  2412.         if (!dcc_paths)
  2413.             filename = strrchr(Client->description, '/');
  2414.  
  2415.         if (!filename)
  2416.             filename = Client->description;
  2417.  
  2418.         if (!count)
  2419.             put_it(format, "Type", " ", "Nick", "Status", "Start time", "Size", "Complete", "Arguments");
  2420.         put_it(format,  
  2421.                 get_dcc_type(flags & DCC_TYPES),
  2422.                 Client->encrypt ? "[E]" : "",
  2423.                 Client->user,
  2424.                 flags&DCC_DELETE ? "Closed" :
  2425.                 flags&DCC_ACTIVE ? "Active" : 
  2426.                 flags&DCC_WAIT ? "Waiting" :
  2427.                 flags&DCC_OFFER ? "Offered" : "Unknown",
  2428.                 stime, size, completed, filename);
  2429.  
  2430.         if (stime && *stime)
  2431.             new_free(&stime);
  2432.         count++;
  2433.     }
  2434. }
  2435.  
  2436. void dcc_glist(char *command, char *args)
  2437. {
  2438. DCC_list    *Client = ClientList;
  2439. char    *dformat =
  2440.             "#$[2]0 $[6]1%Y$2%n $[11]3 $[25]4 $[7]5 $6";
  2441. char    *d1format =
  2442.             "#$[2]0 $[6]1%Y$2%n $[11]3 $4 $[11]5 $[10]6 $[7]7 $8-";
  2443. char    *c1format =
  2444.             "#$[2]0 $[6]1%Y$2%n $[11]3 $4 $[-4]5 $[-4]6 $[-3]7 $[-3]8  $[7]9 $10";
  2445.  
  2446.     unsigned    flags;
  2447.     unsigned    count= 0;
  2448.     int         size = 0;
  2449.     double        barsize = 0.0, perc = 0.0;
  2450.     int         barlen = BAR_LENGTH;
  2451.     char        spec[BIG_BUFFER_SIZE+1];
  2452.     char        *Type;
  2453.         
  2454.     barlen = BAR_LENGTH;
  2455.     barsize = 0.0;
  2456.     memset(spec, 0, sizeof(spec)-1);
  2457.     
  2458.     if (ClientList && do_hook(DCC_HEADER_LIST, "%s %s %s %s %s %s %s", "Dnum","Type","Nick", "Status", "K/s", "File","Encrypt"))
  2459.     {
  2460. #ifdef ONLY_STD_CHARS
  2461.  
  2462.         put_it("%s", convert_output_format("%G#  %W|%n %GT%gype  %W|%n %GN%gick      %W|%n %GP%gercent %GC%gomplete        %W|%n %GK%g/s   %W|%n %GF%gile", NULL, NULL));
  2463.         put_it("%s", convert_output_format("%W---------------------------------------------------------------------------", NULL, NULL));
  2464.  
  2465. #else
  2466.         put_it("%s", convert_output_format("%G#  %W│%n %GT%gype  %W│%n %GN%gick      %W│%n %GP%gercent %GC%gomplete        %W│%n %GK%g/s   %W│%n %GF%gile", NULL, NULL));
  2467.         put_it("%s", convert_output_format("%K──%n─%W─%n─%K─────%n─%W─%n─%K─────────%n─%W─%n─%K───────────────%n─%W─%n─%K─────%n─%W─%n─%K─────%n─%W─%n─%K────────────────", NULL, NULL));
  2468. #endif
  2469.     }
  2470.     for (Client = ClientList ; Client != NULL ; Client = Client->next)
  2471.     {
  2472.         flags = Client->flags & DCC_TYPES;
  2473.         if ((flags == DCC_FILEOFFER || flags == DCC_FILEREAD || flags == DCC_RESENDOFFER || flags == DCC_REGETFILE || flags == DCC_FTPGET || flags == DCC_FTPSEND))
  2474.             if ((Client->flags & DCC_ACTIVE))
  2475.                 continue;
  2476.         Type = get_dcc_type(flags & DCC_TYPES);
  2477.         if (do_hook(DCC_STAT_LIST, "%d %s %s %s %s %s %s", 
  2478.                 Client->dccnum, Type, 
  2479.                 Client->user,
  2480.                 Client->flags & DCC_OFFER ? "Offer" :
  2481.                 Client->flags & DCC_DELETE ? "Close" :
  2482.                 Client->flags & DCC_ACTIVE ? "Active" :
  2483.                 Client->flags & DCC_WAIT ? "Wait" :
  2484. #ifdef DCC_DCNT_PEND
  2485.                 Client->flags & DCC_CNCT_PEND ?    "Connect" :
  2486. #endif
  2487.                 "Unknown",
  2488.                 "N/A", Client->description, Client->encrypt?"E":""))
  2489.         {                
  2490.             time_t u_time = (time_t) time_diff(Client->starttime, get_time(NULL));
  2491.             if ((((flags & DCC_TYPES) == DCC_CHAT) || ((flags & DCC_TYPES) == DCC_RAW) || ((flags & DCC_TYPES) == DCC_BOTMODE) || ((flags & DCC_TYPES) == DCC_FTPOPEN)) && (Client->flags & DCC_ACTIVE))
  2492.             {
  2493.                 put_it("%s", convert_output_format(c1format, "%d %s %s %s %s %s %s %s", 
  2494.                     Client->dccnum, 
  2495.                     Type, 
  2496.                     Client->encrypt ? "E" : " ",
  2497.                     Client->user,
  2498.                     "Active",
  2499.                     convert_time(u_time),
  2500.                     "N/A",
  2501.                     check_paths(Client->description)));
  2502.             }
  2503.             else
  2504.             {
  2505.                 put_it("%s", convert_output_format(dformat, "%d %s %s %s %s %s %s", 
  2506.                     Client->dccnum, 
  2507.                     Type, 
  2508.                     Client->encrypt ? "E" : " ",
  2509.                     Client->user,
  2510.                 
  2511.                     Client->flags & DCC_OFFER ?     "Offer" :
  2512.                     Client->flags & DCC_DELETE ?    "Close" :
  2513.                     Client->flags & DCC_ACTIVE ?    "Active" :
  2514.                     Client->flags & DCC_WAIT ?      "Wait" :
  2515. #ifdef DCC_DCNT_PEND
  2516.                     Client->flags & DCC_CNCT_PEND ?    "Connect" :
  2517. #endif
  2518.                                 "Unknown",
  2519.                     "N/A", 
  2520.                     check_paths(Client->description)));
  2521.             }
  2522.         }
  2523.             
  2524.         count++;
  2525.     }
  2526.     for (Client = ClientList ; Client != NULL ; Client = Client->next)
  2527.     {
  2528.         char    kilobytes[100];
  2529.         time_t    xtime = time(NULL) - Client->starttime.tv_sec;
  2530.         double    bytes = Client->bytes_read + Client->bytes_sent + Client->transfer_orders.byteoffset, 
  2531.             sent;
  2532.         char stats[80];
  2533.         int seconds = 0, minutes = 0;
  2534.         int iperc = 0; 
  2535. #ifdef ONLY_STD_CHARS
  2536.         char *_dcc_offer[12] = {"%K-.........%n",        /*  0 */
  2537.                     "%K-.........%n",        /* 10 */
  2538.                     "%K-=........%n",        /* 20 */
  2539.                     "%K-=*.......%n",        /* 30 */
  2540.                     "%K-=*%1%K=%0%K......%n",    /* 40 */
  2541.                     "%K-=*%1%K=-%0%K.....%n",    /* 50 */
  2542.                     "%K-=*%1%K=-.%0%K....%n",    /* 60 */
  2543.                     "%K-=*%1%K=-. %0%K...%n",    /* 70 */
  2544.                     "%K-=*%1%K=-. %R.%0%K..%n",    /* 80 */
  2545.                     "%K-=*%1%K=-. %R.-%0%K.%n",    /* 90 */
  2546.                     "%K-=*%1%K=-. %R.-=%n",        /* 100 */
  2547.                     ""};
  2548. #else
  2549.         char *_dcc_offer[12] = {"%K▒░░░░░░░░░%n",        /*  0 */
  2550.                     "%K▒░░░░░░░░░%n",        /* 10 */
  2551.                     "%K▒▓░░░░░░░░%n",        /* 20 */
  2552.                     "%K▒▓█░░░░░░░%n",        /* 30 */
  2553.                     "%K▒▓█%1%K▓%0%K░░░░░░%n",    /* 40 */
  2554.                     "%K▒▓█%1%K▓▒%0%K░░░░░%n",    /* 50 */
  2555.                     "%K▒▓█%1%K▓▒░%0%K░░░░%n",    /* 60 */
  2556.                     "%K▒▓█%1%K▓▒░ %0%K░░░%n",    /* 70 */
  2557.                     "%K▒▓█%1%K▓▒░ %R░%0%K░░%n",    /* 80 */
  2558.                     "%K▒▓█%1%K▓▒░ %R░▒%0%K░%n",    /* 90 */
  2559.                     "%K▒▓█%1%K▓▒░ %R░▒▓%n",        /* 100 */
  2560.                     ""};
  2561. #endif
  2562.         char *bar_end;
  2563.         *stats = 0;
  2564.         *kilobytes = 0;
  2565.         perc = 0.0;        
  2566.         sent = bytes - Client->transfer_orders.byteoffset;
  2567.         flags = Client->flags & DCC_TYPES;
  2568.  
  2569.         if ((Client->flags & DCC_WAIT || Client->flags & DCC_OFFER) || ((flags & DCC_FILEOFFER)==0) || ((flags & DCC_FILEREAD) == 0) || ((flags & DCC_RESENDOFFER) == 0) || ((flags & DCC_REGETFILE) == 0))
  2570.             continue;
  2571.             
  2572.         sent /= (double)1024.0;
  2573.         if (xtime <= 0)
  2574.             xtime = 1;
  2575.         sprintf(kilobytes, "%2.4g", sent/(double)xtime);
  2576.     
  2577.         if ((bytes >= 0) && (Client->flags & DCC_ACTIVE)) 
  2578.         {
  2579.             if (bytes && Client->filesize >= bytes)
  2580.             {
  2581.                 perc = (100.0 * ((double)bytes)   / (double)(Client->filesize));
  2582.                 if ( perc > 100.0) perc = 100.0;
  2583.                 else if (perc < 0.0) perc = 0.0;
  2584.                 seconds = (int) (( (Client->filesize - bytes) / (bytes / xtime)) + 0.5);
  2585.                 minutes = seconds / 60;
  2586.                 seconds = seconds - (minutes * 60);
  2587.                 if (minutes > 999) {
  2588.                     minutes = 999;
  2589.                     seconds = 59;
  2590.                 }
  2591.                 if (seconds < 0) seconds = 0;
  2592.             } else
  2593.                 seconds = minutes = perc = 0;
  2594.                 
  2595.             iperc = ((int)perc) / 10;
  2596.             barsize = ((double) (Client->filesize)) / (double) barlen;
  2597.  
  2598.             size = (int) ((double) bytes / (double)barsize);
  2599.     
  2600.             if (Client->filesize == 0)
  2601.                 size = barlen;
  2602.             sprintf(stats, "%4.1f", perc);
  2603.             sprintf(spec, "%s %s%s %02d:%02d", _dcc_offer[iperc], stats, "%%", minutes, seconds);
  2604.             strcpy(spec, convert_output_format(spec, NULL, NULL));
  2605.         }
  2606.         Type = get_dcc_type(flags & DCC_TYPES);        
  2607.         if (do_hook(DCC_STATF_LIST, "%d %s %s %s %s %s %s", 
  2608.             Client->dccnum, Type,
  2609.             Client->user,
  2610.             Client->flags & DCC_OFFER ? "Offer" :
  2611.             Client->flags & DCC_DELETE ? "Close" :
  2612.             Client->flags & DCC_ACTIVE ? "Active" :
  2613.             Client->flags & DCC_WAIT ? "Wait" :
  2614. #ifdef DCC_DCNT_PEND    
  2615.             Client->flags & DCC_CNCT_PEND ?    "Connect" :
  2616. #endif
  2617.             "Unknown",
  2618.             kilobytes, check_paths(Client->description), Client->encrypt?"E":""))
  2619.         {
  2620.             char *s;
  2621.             if (get_int_var(DISPLAY_ANSI_VAR))
  2622.                 if (!get_int_var(DCC_BAR_TYPE_VAR))
  2623.                     s = d1format;
  2624.                 else
  2625.                     s = dformat;
  2626.             else
  2627.                 s = dformat;
  2628.             put_it("%s", convert_output_format(s, "%d %s %s %s %s %s %s", 
  2629.                 Client->dccnum, Type, 
  2630.                 Client->encrypt ? "E":" ",
  2631.                 Client->user,
  2632.                 Client->flags & DCC_OFFER ? "Offer" :
  2633.                 Client->flags & DCC_DELETE ? "Close" :
  2634.                 Client->flags & DCC_ACTIVE ? ((get_int_var(DISPLAY_ANSI_VAR) && !get_int_var(DCC_BAR_TYPE_VAR)) ? spec : "Active"):
  2635.                 Client->flags & DCC_WAIT ? "Wait" :
  2636. #ifdef DCC_DCNT_PEND
  2637.                 Client->flags & DCC_CNCT_PEND ?    "Connect" :
  2638. #endif    
  2639.                 "?????",
  2640.                 kilobytes, 
  2641.                 strip_path(Client->description)));
  2642.         }
  2643.  
  2644.         if (do_hook(DCC_STATF1_LIST, "%s %ld %ld %d %d", 
  2645.             stats,(unsigned long)bytes, (unsigned long)Client->filesize, 
  2646.             minutes, seconds) && (!get_int_var(DISPLAY_ANSI_VAR) || get_int_var(DCC_BAR_TYPE_VAR)))
  2647.         {
  2648.             sprintf(stats, "%4.1f%% (%ld of %ld bytes)", perc, (unsigned long)bytes, (unsigned long)Client->filesize);
  2649.             strcpy( spec, "\002[\026");
  2650.             sprintf(spec+3, "%*s", size+1, " ");
  2651.             bar_end = spec + (strlen(spec));
  2652.             sprintf(bar_end, "%*s", barlen-size+1, " ");
  2653.             strcat(spec, "\026\002]\002 ETA %02d:%02d");
  2654.             memcpy((spec+(((BAR_LENGTH+2) / 2) - (strlen(stats) / 2))), stats, strlen(stats));
  2655.             if (size < barlen)
  2656.             {
  2657.                 memmove(bar_end+1, bar_end, strlen(bar_end));
  2658.                 *bar_end = '\002';
  2659.                 *(bar_end+1) = 0;
  2660.             }
  2661.             put_it(spec, minutes, seconds);    
  2662.         }
  2663.         count++;
  2664.     }
  2665.     if (ClientList && count)
  2666.         do_hook(DCC_POST_LIST, "%s %s %s %s %s %s %s", "DCCnum","Type","Nick", "Status", "K/s", "File","Encrypt");
  2667.     if (count == 0)
  2668.         put_it("%s", convert_output_format("$G %RDCC%n Nothing on DCC list.", NULL, NULL));
  2669. }
  2670.  
  2671. static char DCC_reject_type[12];
  2672. static char DCC_reject_description[40];
  2673.  
  2674. static    void     output_reject_ctcp (char *notused, char *nicklist)
  2675. {
  2676.     if (nicklist && *nicklist && *DCC_reject_description)
  2677.         send_ctcp(CTCP_NOTICE, nicklist, CTCP_DCC,
  2678.             "REJECT %s %s", DCC_reject_type, DCC_reject_description);
  2679.     strcpy(DCC_reject_description, empty_string);
  2680.     strcpy(DCC_reject_type, empty_string);
  2681. }
  2682.  
  2683. /* added by Patch */
  2684. void dcc_close_client_num(unsigned int closenum)
  2685. {
  2686.     DCC_list    *Client, *next;
  2687.     unsigned    flags;
  2688.     char        *Type;
  2689.     int        to_from_idx;
  2690.  
  2691.     for (Client = ClientList ; Client != NULL ; Client = next)
  2692.     {
  2693.         flags = Client->flags;
  2694.         Type = get_dcc_type(flags & DCC_TYPES);
  2695.         /*dcc_types[flags & DCC_TYPES];*/
  2696.         to_from_idx = get_to_from(Type);
  2697.         next = Client->next;
  2698.  
  2699.         if (Client->dccnum == closenum)
  2700.         {
  2701.             if (flags & DCC_DELETE)
  2702.                 return;
  2703.             if ((flags & DCC_WAIT) || (flags & DCC_ACTIVE))
  2704.             {
  2705.                 if (flags & DCC_ACTIVE && to_from_idx != -1)
  2706.                     dcc_update_stats(Client);
  2707.                 if (to_from_idx != -1 && dcc_active_count) dcc_active_count--;
  2708.             }
  2709.  
  2710.             if (do_hook(DCC_LOST_LIST, "%s %s %s", Client->user, Type, 
  2711.                 Client->description? Client->description : "<any>"))
  2712.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), Type, Client->user, Client->description));
  2713.             dcc_reject_notify(Client->description, Client->user, Type);
  2714.             dcc_erase(Client);
  2715.             update_transfer_buffer("");
  2716.             update_all_status(current_window, NULL, 0);
  2717.             return;
  2718.         }
  2719.     }
  2720.  
  2721.     put_it("%s", convert_output_format("%RDCC%n CLOSE number $0 does not exist","%d", closenum));
  2722. }
  2723.  
  2724. /* added by Patch */
  2725. void
  2726. dcc_close_all(void)
  2727. {
  2728.     DCC_list    *Client, *next;
  2729.     unsigned    flags;
  2730.     char        *Type;
  2731.     int        to_from_idx;
  2732.  
  2733.     for (Client = ClientList ; Client != NULL ; Client = next)
  2734.     {
  2735.         flags = Client->flags;
  2736.         Type = get_dcc_type(flags & DCC_TYPES);
  2737.         to_from_idx = get_to_from(Type);
  2738.         next = Client->next;
  2739.         
  2740.         if (flags & DCC_DELETE)
  2741.             continue;
  2742.         if ((flags & DCC_WAIT) || (flags & DCC_ACTIVE))
  2743.         {
  2744.             if (flags & DCC_ACTIVE && to_from_idx != -1)
  2745.                 dcc_update_stats(Client);
  2746.             if (to_from_idx != -1 && dcc_active_count) dcc_active_count--;
  2747.         }
  2748.  
  2749.         if (do_hook(DCC_LOST_LIST, "%s %s %s", Client->user, Type, 
  2750.             Client->description? Client->description : "<any>"))
  2751.             put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), Type, Client->user, Client->description));
  2752.         dcc_reject_notify(Client->description, Client->user, Type);
  2753.         dcc_erase(Client);
  2754.         update_transfer_buffer("");
  2755.         update_all_status(current_window, NULL, 0);
  2756.     }
  2757. }
  2758.  
  2759. /* added by Patch */
  2760. void
  2761. dcc_close_type_all(char *typestr)
  2762. {
  2763.     DCC_list    *Client, *next;
  2764.     unsigned    flags;
  2765.     char        *Type;
  2766.     int        to_from_idx;
  2767.  
  2768.     to_from_idx = get_to_from(typestr);
  2769.  
  2770.     for (Client = ClientList ; Client != NULL ; Client = next)
  2771.     {
  2772.         flags = Client->flags;
  2773.         Type = get_dcc_type(flags & DCC_TYPES);
  2774.         next = Client->next;
  2775.         
  2776.         if (my_stricmp(Type,typestr) == 0)
  2777.         {
  2778.             if (flags & DCC_DELETE)
  2779.                 return;
  2780.             if ((flags & DCC_WAIT) || (flags & DCC_ACTIVE))
  2781.             {
  2782.                 if (flags & DCC_ACTIVE && to_from_idx != -1)
  2783.                     dcc_update_stats(Client);
  2784.                 if (to_from_idx != -1 && dcc_active_count) dcc_active_count--;
  2785.             }
  2786.             if (do_hook(DCC_LOST_LIST, "%s %s %s", Client->user, Type, 
  2787.                 Client->description? Client->description : "<any>"))
  2788.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), Type, Client->user, Client->description));
  2789.             dcc_reject_notify(Client->description, Client->user, Type);
  2790.             dcc_erase(Client);
  2791.             update_transfer_buffer("");
  2792.             update_all_status(current_window, NULL, 0);
  2793.         }
  2794.     }
  2795. }
  2796.  
  2797. /* added by Patch */
  2798. void
  2799. dcc_close_nick_all(char *nickstr)
  2800. {
  2801.     DCC_list    *Client, *next;
  2802.     unsigned    flags;
  2803.     char        *Type;
  2804.     int        to_from_idx;
  2805.  
  2806.     for (Client = ClientList ; Client != NULL ; Client = next)
  2807.     {
  2808.         flags = Client->flags;
  2809.         Type = get_dcc_type(flags & DCC_TYPES);
  2810.         /*dcc_types[flags & DCC_TYPES];*/
  2811.         to_from_idx = get_to_from(Type);
  2812.         next = Client->next;
  2813.         
  2814.         if (my_stricmp(Client->user,nickstr) == 0)
  2815.         {
  2816.             if (flags & DCC_DELETE)
  2817.                 return;
  2818.             if ((flags & DCC_WAIT) || (flags & DCC_ACTIVE))
  2819.             {
  2820.                 if (flags & DCC_ACTIVE && to_from_idx != -1)
  2821.                     dcc_update_stats(Client);
  2822.                 if (to_from_idx != -1 && dcc_active_count) dcc_active_count--;
  2823.             }
  2824.  
  2825.             if (do_hook(DCC_LOST_LIST, "%s %s %s", Client->user, Type, 
  2826.                 Client->description? Client->description : "<any>"))
  2827.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), Type, Client->user, Client->description));
  2828.             dcc_reject_notify(Client->description, Client->user, Type);
  2829.             dcc_erase(Client);
  2830.             update_transfer_buffer("");
  2831.             update_all_status(current_window, NULL, 0);
  2832.         }
  2833.     }
  2834. }
  2835.  
  2836. /* added by Patch */
  2837. void
  2838. dcc_close_type_nick_all(char *typestr, char *nickstr)
  2839. {
  2840.     DCC_list    *Client, *next;
  2841.     unsigned    flags;
  2842.     char        *Type;
  2843.     int        to_from_idx;
  2844.  
  2845.     to_from_idx = get_to_from(typestr);
  2846.  
  2847.     for (Client = ClientList ; Client != NULL ; Client = next)
  2848.     {
  2849.         flags = Client->flags;
  2850.         Type = get_dcc_type(flags & DCC_TYPES);
  2851.         /*dcc_types[flags & DCC_TYPES];*/
  2852.         next = Client->next;
  2853.         
  2854.         if (my_stricmp(Type,typestr) == 0 &&
  2855.             my_stricmp(Client->user,nickstr) == 0)
  2856.         {
  2857.             if (flags & DCC_DELETE)
  2858.                 return;
  2859.             if ((flags & DCC_WAIT) || (flags & DCC_ACTIVE))
  2860.             {
  2861.                 if (flags & DCC_ACTIVE && to_from_idx != -1)
  2862.                     dcc_update_stats(Client);
  2863.                 if (to_from_idx != -1 && dcc_active_count) dcc_active_count--;
  2864.             }
  2865.             if (do_hook(DCC_LOST_LIST, "%s %s %s", Client->user, Type, 
  2866.                 Client->description? Client->description : "<any>"))
  2867.                 put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), Type, Client->user, Client->description));
  2868.             dcc_reject_notify(Client->description, Client->user, Type);
  2869.             dcc_erase(Client);
  2870.             update_transfer_buffer("");
  2871.             update_all_status(current_window, NULL, 0);
  2872.         }
  2873.     }
  2874. }
  2875.  
  2876. /* added by Patch */
  2877. void
  2878. dcc_close_filename(char *filename, char *user, char *Type, int CType)
  2879. {
  2880.     DCC_list    *Client;
  2881.     unsigned    flags;
  2882.     int        to_from_idx;
  2883.  
  2884.     to_from_idx = get_to_from(Type);
  2885.     if ((Client = dcc_searchlist(filename, user, CType, 0, filename, NULL, -1)))
  2886.     {
  2887.         flags = Client->flags;
  2888.         if (flags & DCC_DELETE)
  2889.             return;
  2890.         if ((flags & DCC_WAIT) || (flags & DCC_ACTIVE))
  2891.         {
  2892.             if (flags & DCC_ACTIVE && to_from_idx != -1)
  2893.                 dcc_update_stats(Client);
  2894.             if (to_from_idx != -1 && dcc_active_count) dcc_active_count--;
  2895.         }
  2896.  
  2897.         if (do_hook(DCC_LOST_LIST, "%s %s %s", Client->user, Type, 
  2898.             Client->description? Client->description : "<any>"))
  2899.             put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), Type, Client->user, Client->description));
  2900.         dcc_reject_notify(Client->description, Client->user, Type);
  2901.         dcc_erase(Client);
  2902.         update_transfer_buffer("");
  2903.         update_all_status(current_window, NULL, 0);
  2904.     }
  2905.     else
  2906.         put_it("%s", convert_output_format("$G %RDCC%n No DCC $0:$1 to $2 found","%s %s %s", Type, filename?filename:"(null)",user));
  2907. }
  2908.  
  2909. /* completely rewritten by Patch */
  2910. void dcc_close(char *command, char *args)
  2911. {
  2912.     char        *Type;
  2913.     char        *user;
  2914.     char        *description;
  2915.     int        CType;
  2916.     unsigned int     closenum;
  2917.  
  2918.     Type = next_arg(args, &args);
  2919.     user = next_arg(args, &args);
  2920.     description = next_arg(args, &args);
  2921.  
  2922. /*****************************************************************************
  2923.  DCC CLOSE #all or #number
  2924. *****************************************************************************/
  2925.  
  2926.     if (!Type)
  2927.     {
  2928.         put_it("%s", convert_output_format("$G %RDCC%n You must specify a type|dcc_num for DCC close", NULL, NULL));
  2929.         return;
  2930.     }
  2931.  
  2932.     if ((Type[0] == '#' && !user && *(Type+1) && my_atol(Type+1)) || !my_stricmp(Type, "-all"))
  2933.     {
  2934.         if (!my_stricmp(Type,"-all"))
  2935.         {
  2936.             dcc_close_all();
  2937.             dcc_active_count = 0;
  2938.             update_all_status(current_window, NULL, 0);
  2939.             return;
  2940.         }
  2941.  
  2942.         closenum = atol(Type+1);
  2943.  
  2944.         if (closenum == 0)
  2945.         {
  2946.             put_it("%s", convert_output_format("$G %RDCC%n close invalid number", NULL, NULL));
  2947.             return;
  2948.         }
  2949.  
  2950.         dcc_close_client_num(closenum);
  2951.         update_all_status(current_window, NULL, 0);
  2952.         return;
  2953.     }
  2954.  
  2955. /*****************************************************************************
  2956.  DCC CLOSE SEND|GET|RESEND|REGET|nick #all
  2957. *****************************************************************************/
  2958.  
  2959.     if (!user)
  2960.     {
  2961.         put_it("%s", convert_output_format("$G %RDCC%n specify a type and a nick for DCC close", NULL, NULL));
  2962.         return;
  2963.     }
  2964.  
  2965.     for (CType = 0; dcc_types[CType] != NULL; CType++)
  2966.         if (!my_stricmp(Type, dcc_types[CType])) break;
  2967.  
  2968.     if (user[0] == '#' && !description && (my_atol(user+1) || my_stricmp(user+1, "all")==0))
  2969.     {
  2970.         if (my_stricmp(user+1,"all") == 0)
  2971.         {
  2972.             if (!dcc_types[CType])
  2973.                 dcc_close_nick_all(Type);
  2974.             else
  2975.                 dcc_close_type_all(Type);
  2976.             update_all_status(current_window, NULL, 0);
  2977.             return;
  2978.         }
  2979.         put_it("%s", convert_output_format("$G %RDCC%n close invalid number", NULL, NULL));
  2980.         return;
  2981.     }
  2982.  
  2983. /*****************************************************************************
  2984.  DCC CLOSE SEND|GET|RESEND|REGET nick #all|filename
  2985. *****************************************************************************/
  2986.  
  2987.     if (description && *description == '-')
  2988.     {
  2989.         if (!my_stricmp(description,"-all"))
  2990.             dcc_close_type_nick_all(Type,user);
  2991.         else 
  2992.         put_it("%s", convert_output_format("$G %RDCC%n CLOSE invalid description", NULL, NULL));
  2993.         return;
  2994.     }
  2995.  
  2996.     if (dcc_types[CType])
  2997.         dcc_close_filename(description, user, Type, CType);
  2998.     else
  2999.         put_it("%s", convert_output_format("$G %RDCC%n Unknown type [$0]", "%s", dcc_types[CType]));
  3000. }
  3001.  
  3002. void dcc_reject_notify(char *description, char *user, char *Type)
  3003. {
  3004.     strcpy(DCC_reject_description, description ? description : "(null)");
  3005.     if (!my_stricmp(Type, "TSEND"))
  3006.         strcpy(DCC_reject_type, "TGET");
  3007.     else if (!my_stricmp(Type, "TGET"))
  3008.         strcpy(DCC_reject_type, "TSEND");
  3009.     else if (!my_stricmp(Type, "TREGET"))
  3010.         strcpy(DCC_reject_type, "TRESEND");
  3011.     else if (!my_stricmp(Type, "TRESEND"))
  3012.         strcpy(DCC_reject_type, "TREGET");
  3013.     else if (!my_stricmp(Type, "SEND"))
  3014.         strcpy(DCC_reject_type, "GET");
  3015.     else if (!my_stricmp(Type, "GET"))
  3016.         strcpy(DCC_reject_type, "SEND");
  3017.     else if (!my_stricmp(Type, "RESEND"))
  3018.         strcpy(DCC_reject_type, "REGET");
  3019.     else if (!my_stricmp(Type, "REGET"))
  3020.         strcpy(DCC_reject_type, "RESEND");
  3021.     else
  3022.         strcpy(DCC_reject_type, Type);
  3023.     if (*user == '=')
  3024.         user++;
  3025.     add_ison_to_whois (user, output_reject_ctcp);
  3026. }
  3027.  
  3028. extern void dcc_reject (char *from, char *type, char *args)
  3029. {
  3030.     DCC_list    *Client;
  3031.     char    *description;
  3032.     int    CType;
  3033.     int    tdcc = 0;
  3034.     
  3035.     upper(type);
  3036.     if (*type == 'T' && *(type+1))
  3037.         tdcc = 1;
  3038.     for (CType = 0; dcc_types[CType] != NULL; CType++)
  3039.         if (!strcmp(type+tdcc, dcc_types[CType]))
  3040.             break;
  3041.  
  3042.     if (!dcc_types[CType])
  3043.         return;
  3044.     if (tdcc)
  3045.         CType |= DCC_TDCC;
  3046.         
  3047.     description = next_arg(args, &args);
  3048.  
  3049.     if ((Client = dcc_searchlist(NULL, from, CType, 0, description, NULL, -1)))
  3050.     {
  3051.         if (Client->flags & DCC_DELETE)
  3052.             return;
  3053.                 if (do_hook(DCC_LOST_LIST,"%s %s %s REJECTED", from, type, description ? description : "<any>"))
  3054.             put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_ERROR_FSET), "%s %s %s %s", update_clock(GET_TIME), type, Client->user, Client->description));
  3055.         update_transfer_buffer("");
  3056.         Client->flags |= DCC_DELETE;
  3057.         update_all_status(current_window, NULL, 0);
  3058. #ifdef WANT_CDCC
  3059.         dcc_sendfrom_queue();
  3060. #endif
  3061.     }
  3062. }
  3063.  
  3064. static    void        dcc_rename (char *command, char *args)
  3065. {
  3066.     DCC_list    *Client;
  3067.     char    *user;
  3068.     char    *description;
  3069.     char    *newdesc;
  3070.     char    *temp;
  3071.     
  3072.     if (!(user = next_arg(args, &args)) || !(temp = next_arg(args, &args)))
  3073.     {
  3074.         put_it("%s", convert_output_format("$G %RDCC%n You must specify a nick and a new filename", NULL, NULL));
  3075.         return;
  3076.     }
  3077.     if ((newdesc = next_arg(args, &args)) != NULL)
  3078.         description = temp;
  3079.     else
  3080.     {
  3081.         newdesc = temp;
  3082.         description = NULL;
  3083.     }
  3084.  
  3085.     if ((Client = dcc_searchlist(description, user, DCC_FILEREAD, 0, NULL, NULL, 0)))
  3086.     {
  3087.         /* Is this needed now? */
  3088.         if (!(Client->flags & DCC_OFFER))
  3089.         {
  3090.             put_it("%s", convert_output_format("$G %RDCC Too late to rename that file", NULL, NULL));
  3091.             return;
  3092.         }
  3093.         malloc_strcpy(&(Client->description), newdesc);
  3094.         put_it("%s", convert_output_format("$G %RDCC File $0 from $1 rename to $2", "%s %s %s", description?description:"(null)", user, newdesc));
  3095.     }
  3096.     else
  3097.         put_it("%s", convert_output_format("$G %RDCC No file $0 from $1 found, or it's too late to rename", "%s %s", description?description:"(null)", user));
  3098. }
  3099.  
  3100. /*
  3101.  * close_all_dcc:  We call this when we create a new process so that
  3102.  * we don't leave any fd's lying around, that won't close when we
  3103.  * want them to..
  3104.  */
  3105. extern void close_all_dcc _((void))
  3106. {
  3107.     DCC_list *Client, *last;
  3108.  
  3109.     for (Client = ClientList; Client; Client = last)
  3110.     {
  3111.         last = Client->next;
  3112.         dcc_erase(Client);
  3113.     }
  3114.     dcc_active_count = 0;
  3115. }
  3116.  
  3117.  
  3118. /* Looks for the dcc transfer that is "current" (last recieved data)
  3119.  * and returns information for it
  3120.  */
  3121. extern char *DCC_get_current_transfer _((void))
  3122. {
  3123.     return DCC_current_transfer_buffer;
  3124. }
  3125.  
  3126. BUILT_IN_COMMAND(chat)
  3127. {
  3128. int no_chat = 0;
  3129.     if (!my_strnicmp(command, "NOC", 3))
  3130.         no_chat = 1;
  3131.     if (args && *args)
  3132.     {
  3133.         char *tmp = NULL;
  3134.         if (no_chat)
  3135.             malloc_sprintf(&tmp, "CLOSE CHAT %s", args);
  3136.         else
  3137.             malloc_sprintf(&tmp, "CHAT %s", args);
  3138.         process_dcc(tmp);
  3139.         new_free(&tmp);
  3140.     }
  3141.     else if (last_chat_req)
  3142.     {
  3143.         DCC_list *chat_req = NULL;
  3144.         if ((chat_req = dcc_searchlist("chat", last_chat_req, DCC_CHAT, 0, NULL, NULL, no_chat?-1:0)))
  3145.         {
  3146.             if (no_chat)
  3147.             {
  3148.                 dcc_close_filename(NULL, last_chat_req, "CHAT", DCC_CHAT);
  3149.                 new_free(&last_chat_req);
  3150.             }
  3151.             else    
  3152.             {
  3153.                 char nick[BIG_BUFFER_SIZE];
  3154.                 dcc_open(chat_req);
  3155.                 sprintf(nick, "=%s", chat_req->user);
  3156.                 addtabkey(nick, "msg", 0);
  3157.             }
  3158.         }
  3159.         else
  3160.             bitchsay("Error occurred");
  3161.     } else 
  3162.         userage(command, helparg);
  3163. }
  3164.  
  3165.  
  3166. static void DCC_close_filesend (DCC_list *Client, char *type)
  3167. {
  3168.     char    lame_ultrix[30];    /* should be plenty */
  3169.     char    lame_ultrix2[30];
  3170.     char    lame_ultrix3[30];
  3171.     char    buffer[200];
  3172.     char     *tofrom = NULL;
  3173.     time_t xtime;
  3174.     double xfer;
  3175.  
  3176.     xtime = time_diff(Client->starttime, get_time(NULL));
  3177.     xfer = (double)(Client->bytes_sent ? Client->bytes_sent : Client->bytes_read);
  3178.  
  3179.     if (xfer <= 0)
  3180.         xfer = 1;
  3181.     if (xtime <= 0)
  3182.         xtime = 1;
  3183.     sprintf(lame_ultrix, "%2.4g", (xfer/ 1024.0 / xtime));
  3184.     /* Cant pass %g to put_it (lame ultrix/dgux), fix suggested by sheik. */
  3185.     sprintf(lame_ultrix2, "%2.4g%s", _GMKv(xfer), _GMKs(xfer));
  3186.     sprintf(lame_ultrix3, "%2.4g", (double)xtime);
  3187.     sprintf(buffer, "%%s %s %%s %%s TRANSFER COMPLETE", type);
  3188.  
  3189.     switch(get_to_from(dcc_types[Client->flags&DCC_TYPES]))
  3190.     {
  3191.         case 0:
  3192.         case 1:
  3193.             tofrom = "to";
  3194.             break;
  3195.         case 2:
  3196.         case 3:
  3197.             tofrom = "from";
  3198.             break;
  3199.         default:
  3200.             tofrom = "to";
  3201.             break;
  3202.     }
  3203.     if(do_hook(DCC_LOST_LIST,buffer,Client->user, check_paths(Client->description), lame_ultrix))
  3204.         put_it("%s", convert_output_format(fget_string_var(FORMAT_DCC_LOST_FSET),
  3205.         "%s %s %s %s %s %s %s %s %s", update_clock(GET_TIME), type, 
  3206.         check_paths(Client->description), lame_ultrix2, tofrom, Client->user, 
  3207.         lame_ultrix3, lame_ultrix, "Kb"));
  3208.  
  3209.     dcc_update_stats(Client);
  3210.     if (get_to_from(dcc_types[Client->flags&DCC_TYPES]) != -1 && dcc_active_count)
  3211.         dcc_active_count--;
  3212.  
  3213.     if (Client->read != Client->write)
  3214.         close (Client->write);
  3215.     FD_CLR(Client->write, &writables);
  3216.  
  3217.     new_close(Client->read);
  3218.     new_close(Client->file);
  3219.  
  3220.     Client->file = Client->read = Client->write = -1;
  3221.     Client->flags |= DCC_DELETE;
  3222.     *DCC_current_transfer_buffer = 0;
  3223.     update_transfer_buffer("");
  3224.     update_all_status(current_window, NULL, 0);
  3225. }
  3226.  
  3227. char transfer_buffer[BIG_BUFFER_SIZE];
  3228.  
  3229. static void update_transfer_buffer (char *format, ...)
  3230. {
  3231.     register DCC_list    *Client = ClientList;
  3232.     unsigned    count= 0;
  3233.     double        perc = 0.0;
  3234.     char temp_str[60];
  3235.         
  3236.     errno = 0;
  3237.     *transfer_buffer = 0;
  3238.     for (Client = ClientList ; Client; Client = Client->next)
  3239.     {
  3240.         double    bytes;
  3241.         unsigned long flags = Client->flags & DCC_TYPES;
  3242.         
  3243.         if ((flags == DCC_RAW) || (flags == DCC_RAW_LISTEN) || (flags == DCC_CHAT) || (flags == DCC_BOTMODE) || (flags == DCC_FTPOPEN))
  3244.             continue;
  3245.         if ((Client->flags & DCC_WAIT) || (Client->flags == DCC_DELETE))
  3246.             continue;
  3247.         bytes = Client->bytes_read + Client->bytes_sent + Client->transfer_orders.byteoffset;
  3248.         if (bytes >= 0) 
  3249.         {
  3250.             if (Client->filesize >= bytes && (Client->filesize > 0))
  3251.             {
  3252.                 perc = (100.0 * ((double)bytes)   / (double)(Client->filesize));
  3253.                 if ( perc > 100.0) perc = 100.0;
  3254.                 else if (perc < 0.0) perc = 0.0;
  3255.  
  3256.             }                
  3257.             sprintf(temp_str,"%d%%,",(int) perc);
  3258.             strcat(transfer_buffer,temp_str);
  3259.         }
  3260.         if (count++ > 9)
  3261.             break;
  3262.     }
  3263.     if (count)
  3264.     {
  3265.         chop(transfer_buffer, 1);
  3266.         if (fget_string_var(FORMAT_DCC_FSET))
  3267.         {
  3268.             sprintf(DCC_current_transfer_buffer, convert_output_format(fget_string_var(FORMAT_DCC_FSET), "%s", transfer_buffer));
  3269.             chop(DCC_current_transfer_buffer, 4);
  3270.         }
  3271.         else
  3272.             sprintf(DCC_current_transfer_buffer, "[%s]", transfer_buffer);
  3273.     }
  3274.     else
  3275.         *DCC_current_transfer_buffer = 0;
  3276. }
  3277.  
  3278. int get_to_from(char *Type) {
  3279.     if (!my_stricmp(Type, "SEND"))
  3280.         return 0;
  3281.     else if (!my_stricmp(Type, "RESEND"))
  3282.         return 1;
  3283.     else if (!my_stricmp(Type, "GET"))
  3284.         return 2;
  3285.     else if (!my_stricmp(Type, "REGET"))
  3286.         return 3;
  3287.     else if (!my_stricmp(Type, "TSEND"))
  3288.         return 4;
  3289.     else if (!my_stricmp(Type, "TRESEND"))
  3290.         return 5;
  3291.     else if (!my_stricmp(Type, "TGET"))
  3292.         return 6;
  3293.     else if (!my_stricmp(Type, "TREGET"))
  3294.         return 7;
  3295.     else 
  3296.         return -1;
  3297. }
  3298.  
  3299. static void dcc_help1 (char *command, char *args)
  3300. {
  3301. char *comm;
  3302. int i, c;
  3303. char buffer[BIG_BUFFER_SIZE+1];
  3304.     if (args && *args)
  3305.     {
  3306.         comm = next_arg(args, &args);
  3307.         upper(comm);
  3308.         for (i = 0; dcc_commands[i].name != NULL; i++)
  3309.         {
  3310.             if (!strncmp(comm, dcc_commands[i].name, strlen(comm)))
  3311.             {
  3312.                 put_it("%s", convert_output_format("$G Usage: %W/%R$0%n $1 %K-%n $2-", "DCC %s %s", dcc_commands[i].name, dcc_commands[i].help?dcc_commands[i].help:"No help availble yet"));
  3313.                 return;
  3314.             }
  3315.         }
  3316.     }
  3317.     put_it("%s", convert_output_format("$G %RDCC%n help -", NULL, NULL));
  3318.     *buffer = 0;
  3319.     c = 0;
  3320.     for (i = 0; dcc_commands[i].name; i++)
  3321.     {
  3322.         strcat(buffer, dcc_commands[i].name);
  3323.         strcat(buffer, space);
  3324.         if (++c == 5)
  3325.         {
  3326.             put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
  3327.             *buffer = 0;
  3328.             c = 0;
  3329.         }
  3330.     }
  3331.     if (c)
  3332.         put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
  3333.     userage("dcc help", "[command] to get help on specific commands");
  3334. }
  3335.  
  3336. static void dcc_show_active(char *command, char * args) 
  3337. {
  3338.     put_it("%s", convert_output_format("$G %RDCC%n  DCC Active = \002$0\002, Limit = \002$1\002", 
  3339.         "%d %d", dcc_active_count, get_int_var(DCC_SEND_LIMIT_VAR)));
  3340. }
  3341.  
  3342. static void dcc_set_quiet(char *command, char *args ) 
  3343. {
  3344.     dcc_quiet ^=1;
  3345.     put_it("%s", convert_output_format("$G %RDCC%n  DCC Quiet = \002$0\002", "%s", on_off(dcc_quiet)));
  3346. }
  3347.  
  3348. /* returns the string without the path (if present) */
  3349. static char * strip_path(char *str)
  3350. {
  3351.     char *ptr;
  3352.  
  3353.     ptr = strrchr(str,'/');
  3354.     if (ptr == NULL)
  3355.         return str;
  3356.     else
  3357.         return ptr+1;
  3358. }
  3359.  
  3360. /* returns the string without the path (if present) */
  3361. static char *check_paths(char *str)
  3362. {
  3363.     if (dcc_paths == 0)
  3364.         return strip_path(str);
  3365.     else
  3366.         return str;
  3367. }
  3368.  
  3369. static void dcc_set_paths(char *command, char *args)
  3370. {
  3371.     dcc_paths ^= 1;
  3372.     
  3373.     put_it("%s", convert_output_format("$G %RDCC%n  DCC paths is now \002$0\002", "%s", on_off(dcc_paths)));
  3374. }    
  3375.  
  3376. static void dcc_tog_rename(char *command, char *args)
  3377. {
  3378. int    arename = get_int_var(DCC_AUTORENAME_VAR);
  3379.     arename ^= 1;
  3380.     set_int_var(DCC_AUTORENAME_VAR, arename);
  3381.     put_it("%s", convert_output_format("$G %RDCC%n  DCC auto rename is now \002$0\002", "%s", on_off(get_int_var(DCC_AUTORENAME_VAR))));
  3382. }    
  3383.  
  3384. static void dcc_overwrite_toggle(char *command, char *args)
  3385. {
  3386.     dcc_overwrite_var ^= 1;
  3387.     
  3388.     put_it("%s", convert_output_format("  DCC overwrite is now \002$0\002", "%s", on_off(dcc_overwrite_var)));
  3389. }    
  3390.  
  3391. void dcc_tog_auto(char *command, char *args)
  3392. {
  3393.     int dcc_auto = get_int_var(DCC_AUTOGET_VAR);
  3394.     dcc_auto ^= 1;
  3395.     set_int_var(DCC_AUTOGET_VAR, dcc_auto);    
  3396.     put_it("%s", convert_output_format("  DCC autoget is now \002$0\002", "%s", on_off(dcc_auto)));
  3397. }    
  3398.  
  3399. void dcc_stats (char *command, char *unused)
  3400. {
  3401. char max_rate_in[20];
  3402. char min_rate_in[20];
  3403. char max_rate_out[20];
  3404. char min_rate_out[20];
  3405.  
  3406.     sprintf(max_rate_in, "%6.2f", dcc_max_rate_in/1024.0);
  3407.     sprintf(min_rate_in, "%6.2f", ((dcc_min_rate_in != DBL_MAX )?dcc_min_rate_in/1024.0: 0.0));
  3408.     sprintf(max_rate_out, "%6.2f", dcc_max_rate_out/1024.0);
  3409.     sprintf(min_rate_out, "%6.2f", ((dcc_min_rate_out != DBL_MAX) ? dcc_min_rate_out/1024.0: 0.0));
  3410.     if (do_hook(DCC_TRANSFER_STAT_LIST, "%lu %s %s %lu %s %s %lu %u %u %s %s %s %s", 
  3411.         (unsigned long)dcc_bytes_in, max_rate_in, min_rate_in,
  3412.         (unsigned long)dcc_bytes_out, max_rate_out, min_rate_out,
  3413.         (unsigned long)(send_count_stat+get_count_stat), 
  3414.         dcc_active_count, get_int_var(DCC_SEND_LIMIT_VAR),
  3415.         on_off(get_int_var(DCC_AUTOGET_VAR)), on_off(dcc_paths), 
  3416.         on_off(dcc_quiet), on_off(dcc_overwrite_var)))
  3417.     {
  3418.         char in[50], out[50];
  3419.         sprintf(in,  "%3.2f%s", _GMKv(dcc_bytes_in),  _GMKs(dcc_bytes_in));
  3420.         sprintf(out, "%3.2f%s", _GMKv(dcc_bytes_out), _GMKs(dcc_bytes_out));
  3421.  
  3422. #ifdef ONLY_STD_CHARS
  3423.         put_it("%s",convert_output_format("       %G========================%K[%Cdcc transfer stats%K]%G=======================", NULL));
  3424.         put_it("%s",convert_output_format("       %G|                                                                 |", NULL));
  3425.         put_it("%s",convert_output_format("       %G|%g|-%K[%Cx%cferd %Ci%cn%K]%g-|-%K[%Cx%cferd %Co%cut%K]%g-|-%K[%Ct%cotal %Cf%ciles%K]%g-|-%K[%Ca%cctive%K]%g-|-[%Cl%cimit%K]%g-|%G|", NULL));
  3426.         put_it("%s",convert_output_format("       %G|%g| %W$[-10]0 %g|  %W$[-10]1 %g|    %W$[-10]2 %g| %W$[-8]3 %g| %W$[-7]4 %g|%G|", "%s %s %d %d %d", in, out,send_count_stat+get_count_stat,dcc_active_count,get_int_var(DCC_SEND_LIMIT_VAR)));
  3427.         put_it("%s",convert_output_format("       %G|%g|------------|-------------|---------------|----------|---------|%G|", NULL));
  3428.         put_it("%s",convert_output_format("       %G|                                                                 |", NULL));
  3429.         put_it("%s",convert_output_format("       %g|----%K[%Ci%cn %Cs%ctats%K]%g---|---%K[%Co%cut %Cs%ctats%K]%g---|----------%K[%Ct%coggles%K]%g----------|", NULL));
  3430.         put_it("%s",convert_output_format("       %g| %Cm%nax: %W$[-6]0%n%Rkb/s %g| %Cm%nax: %W$[-6]1%n%Rkb/s %g|   %Ca%nutoget: %W$[-3]2%n   %Cp%naths: %W$[-3]3 %g|", "%s %s %s %s", max_rate_in, max_rate_out, on_off(get_int_var(DCC_AUTOGET_VAR)),on_off(dcc_pat
  3431.  
  3432.  
  3433. hs)));
  3434.         put_it("%s",convert_output_format("       %g| %Cm%nin: %W$[-6]0%n%Rkb/s %g| %Cm%nin: %W$[-6]1%n%Rkb/s %g| %Co%nverwrite: %W$[-3]2%n   %Cq%nuiet: %W$[-3]3 %g|", "%s %s %s %s", min_rate_in, min_rate_out, on_off(dcc_overwrite_var), on_off(dcc_quiet)));
  3435.         put_it("%s",convert_output_format("       %g|-----------------|-----------------|-----------------------------|", NULL));
  3436.  
  3437. #else
  3438.  
  3439.         put_it("%s",convert_output_format("       %G╒═══════════════════════%K[%Cdcc transfer stats%K]%G══════════════════════╕", NULL));
  3440.         put_it("%s",convert_output_format("       %G│                                                                 │", NULL));
  3441.         put_it("%s",convert_output_format("       %G│%g╓─%K[%Cx%cferd %Ci%cn%K]%g─╓-%K[%Cx%cferd %Co%cut%K]%g─╖─%K[%Ct%cotal %Cf%ciles%K]%g─╓─%K[%Ca%cctive%K]%g─╖─[%Cl%cimit%K]%g─╖%G│", NULL));
  3442.         put_it("%s",convert_output_format("       %G│%g║ %W$[-10]0 %g║  %W$[-10]1 %g║    %W$[-10]2 %g║ %W$[-8]3 %g║ %W$[-7]4 %g║%G│", "%s %s %d %d %d", in, out,send_count_stat+get_count_stat,dcc_active_count,get_int_var(DCC_SEND_LIMIT_VAR)));
  3443.         put_it("%s",convert_output_format("       %G│%g╙────────────╜─────────────╙───────────────╜──────────╙─────────╜%G│", NULL));
  3444.         put_it("%s",convert_output_format("       %G│                                                                 │", NULL));
  3445.         put_it("%s",convert_output_format("       %g╓────%K[%Ci%cn %Cs%ctats%K]%g───╓───%K[%Co%cut %Cs%ctats%K]%g───╖──────────%K[%Ct%coggles%K]%g──────────╖", NULL));
  3446.         put_it("%s",convert_output_format("       %g║ %Cm%nax: %W$[-6]0%n%Rkb/s %g║ %Cm%nax: %W$[-6]1%n%Rkb/s %g║   %Ca%nutoget: %W$[-3]2%n   %Cp%naths: %W$[-3]3 %g║", "%s %s %s %s", max_rate_in, max_rate_out, on_off(get_int_var(DCC_AUTOGET_VAR)),on_off(dcc_pat
  3447. hs)));
  3448.         put_it("%s",convert_output_format("       %g║ %Cm%nin: %W$[-6]0%n%Rkb/s %g║ %Cm%nin: %W$[-6]1%n%Rkb/s %g║ %Co%nverwrite: %W$[-3]2%n   %Cq%nuiet: %W$[-3]3 %g║", "%s %s %s %s", min_rate_in, min_rate_out, on_off(dcc_overwrite_var), on_off(dcc_quiet)));
  3449.         put_it("%s",convert_output_format("       %g╙─────────────────╜─────────────────╙─────────────────────────────╜", NULL));
  3450.  
  3451. #endif
  3452.  
  3453.     }
  3454. }
  3455.  
  3456. /*
  3457.  * only call this on dcc finish
  3458.  */
  3459. static void dcc_update_stats (DCC_list *Client)
  3460. {
  3461. time_t    xtime = time_diff(Client->starttime, get_time(NULL));
  3462.     
  3463.     dcc_bytes_in += Client->bytes_read;
  3464.     dcc_bytes_out += Client->bytes_sent;
  3465.     if (xtime <= 0)
  3466.         xtime = 1;
  3467.     if (Client->bytes_read)
  3468.     {
  3469.         get_count_stat++;
  3470.         if ((double)Client->bytes_read/(double)xtime > dcc_max_rate_in)
  3471.             dcc_max_rate_in = (double)Client->bytes_read/(double)xtime;
  3472.         if ((double)Client->bytes_read/ (double)xtime < dcc_min_rate_in)
  3473.             dcc_min_rate_in = (double)Client->bytes_read/(double)xtime;    
  3474.     }
  3475.     if (Client->bytes_sent)
  3476.     {
  3477.         send_count_stat++;
  3478.         if ((double)Client->bytes_sent/(double)xtime > dcc_max_rate_out)
  3479.             dcc_max_rate_out = (double)Client->bytes_sent/(double)xtime;
  3480.         if ((double)Client->bytes_sent/(double)xtime < dcc_min_rate_out)
  3481.             dcc_min_rate_out = (double)Client->bytes_sent/ (double)xtime;    
  3482.     }
  3483. }
  3484.  
  3485. unsigned char byteordertest(void)
  3486. {
  3487.     unsigned short test = DCC_PACKETID;
  3488.  
  3489.     if (*((unsigned char *)&test) == ((DCC_PACKETID & 0xff00) >> 8))
  3490.         return 0;
  3491.  
  3492.     if (*((unsigned char *)&test) == (DCC_PACKETID & 0x00ff))
  3493.         return 1;
  3494.     return 0;
  3495. }
  3496.  
  3497. /*
  3498.  * This stuff doesnt conform to the protocol.
  3499.  * Thanks mirc for disregarding the protocol.
  3500.  */
  3501. #ifdef MIRC_BROKEN_DCC_RESUME
  3502. extern  int doing_msg, doing_notice;
  3503.  
  3504. /*
  3505.  * Usage: /DCC RESUME <nick> [file] [-e passkey]
  3506.  */
  3507. void    dcc_getfile_resume (char *command, char *args)
  3508. {
  3509.     char        *user, *nick;
  3510.     char        *filename = NULL;
  3511.     char        *fullname = NULL;
  3512.     char        *tmp = NULL;
  3513.     DCC_list    *Client;
  3514.     char        *passwd = NULL;
  3515.     struct stat    sb;
  3516.     char        buf[10];
  3517.  
  3518. #ifdef PUBLIC_ACCESS
  3519.     bitchsay("This command has been disabled on a public access system");
  3520.     return;
  3521. #endif
  3522.     if (!(user = next_arg(args, &args)))
  3523.     {
  3524.         say("You must supply a nickname for DCC RESUME");
  3525.         return;
  3526.     }
  3527.  
  3528.     if (args && *args)
  3529.     {
  3530.         /* Leeme lone, Yoshi. :P */
  3531.         if (args[0] != '-' || args[1] != 'e')
  3532.             filename = next_arg(args, &args);
  3533.  
  3534.         if (args && args[0] == '-' && args[1] == 'e')
  3535.         {
  3536.             next_arg(args, &args);
  3537.             passwd = next_arg(args, &args);
  3538.         }
  3539.     }
  3540.  
  3541.  
  3542.     while ((nick = next_in_comma_list(user, &user)))
  3543.     {
  3544.         if (!nick || !*nick)
  3545.             break;
  3546.         if (!(Client = dcc_searchlist(filename, nick, DCC_FILEREAD, 0, NULL, NULL, 0)))
  3547.         {
  3548.             if (filename)
  3549.                 say("No file (%s) offered in SEND mode by %s", filename, nick);
  3550.             else
  3551.                 say("No file offered in SEND mode by %s", nick);
  3552.             return;
  3553.         }
  3554.  
  3555.         if (get_string_var(DCC_DLDIR_VAR))
  3556.             malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), Client->description);
  3557.         else
  3558.             tmp = m_strdup(Client->description);
  3559.  
  3560.         if (!(fullname = expand_twiddle(tmp)))
  3561.             malloc_strcpy(&fullname, tmp);
  3562.         /*
  3563.          * This has to be done by hand, we cant use send_ctcp,
  3564.          * because this violates the protocol, and send_ctcp checks
  3565.          * for that.  Ugh.
  3566.          */
  3567.  
  3568.         if (stat(fullname, &sb) == -1)
  3569.         {
  3570.             /* File doesnt exist.  Sheesh. */
  3571.             say("DCC RESUME: Cannot use DCC RESUME if the file doesnt exist. [%s|%s]", fullname, strerror(errno));
  3572.             return;
  3573.         }
  3574.  
  3575.         if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  3576.         {
  3577.             say("A previous DCC GET:%s to %s exists", filename?filename:"<any>", nick);
  3578.             return;
  3579.         }
  3580.  
  3581.         if (passwd)
  3582.             Client->encrypt = m_strdup(passwd);
  3583.         Client->bytes_sent = 0L;
  3584.         Client->transfer_orders.byteoffset = sb.st_size;
  3585.  
  3586.         sprintf(buf, "%hd", ntohs(Client->remport));
  3587.         malloc_strcpy(&Client->othername, buf);
  3588.  
  3589.         malloc_strcpy(&Client->othername, ltoa((long)ntohs(Client->remport)));
  3590.  
  3591.         /* Just in case we have to fool the protocol enforcement. */
  3592.         doing_privmsg = doing_notice = in_ctcp_flag = 0;
  3593.         send_ctcp(CTCP_PRIVMSG, nick, CTCP_DCC, "RESUME %s %d %d", Client->description, ntohs(Client->remport), (unsigned int)sb.st_size);
  3594.     }
  3595.     
  3596.     new_free(&tmp);
  3597.     new_free(&fullname);
  3598.     /* Then we just sit back and wait for the reply. */
  3599. }
  3600.  
  3601. /*
  3602.  * When the peer demands DCC RESUME
  3603.  * We send out a DCC ACCEPT
  3604.  */
  3605. static void dcc_getfile_resume_demanded (char *user, char *filename, char *port, char *offset)
  3606. {
  3607.     DCC_list    *Client;
  3608.  
  3609.     if (!(Client = dcc_searchlist(filename, user, DCC_FILEOFFER, 0, port, NULL, 0)))
  3610.         return;        /* Its a fake. */
  3611.  
  3612.     if (!offset)
  3613.         return;        /* Its a fake */
  3614.  
  3615.     Client->transfer_orders.byteoffset = my_atol(offset);
  3616.     Client->bytes_read = 0L;
  3617.  
  3618.     doing_privmsg = doing_notice = in_ctcp_flag = 0;
  3619.     send_ctcp(CTCP_PRIVMSG, user, CTCP_DCC, "ACCEPT %s %s %s", filename, port, offset);
  3620.  
  3621.     /* Wait for them to open the connection */
  3622. }
  3623.  
  3624.  
  3625. /*
  3626.  * When we get the DCC ACCEPT
  3627.  * We start the connection
  3628.  */
  3629. static    void    dcc_getfile_resume_start (char *nick, char *filename, char *port, char *offset)
  3630. {
  3631.     DCC_list    *Client;
  3632.     char        *fullname = NULL;
  3633.     char        *tmp = NULL;
  3634.     
  3635. #ifdef PUBLIC_ACCESS
  3636.     bitchsay("This command has been disabled on a public access system");
  3637.     return;
  3638. #endif
  3639.     if (!(Client = dcc_searchlist(filename, nick, DCC_FILEREAD, 0, port, NULL, 0)))
  3640.         return;        /* Its fake. */
  3641.  
  3642.     Client->flags |= DCC_TWOCLIENTS;
  3643.     if (!dcc_open(Client))
  3644.         return;
  3645.  
  3646.     if (get_string_var(DCC_DLDIR_VAR))
  3647.         malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), Client->description);
  3648.     else
  3649.         tmp = m_strdup(Client->description);
  3650.     if (0 == (fullname = expand_twiddle(tmp)))
  3651.         malloc_strcpy(&fullname, tmp);
  3652.  
  3653. #if defined(WINNT) || defined(__EMX__)
  3654.     if (!(Client->file = open(fullname, O_WRONLY | O_APPEND | O_BINARY/*, 0644*/)))
  3655. #else
  3656.     if (!(Client->file = open(fullname, O_WRONLY | O_APPEND, 0644)))
  3657. #endif
  3658.     {
  3659.         put_it("%s", convert_output_format("$G %RDCC%n Unable to open $0: $1-", "%s %s", Client->description, errno?strerror(errno):"Unknown"));
  3660.         Client->flags |= DCC_DELETE;
  3661.     }
  3662.  
  3663.     new_free(&fullname);
  3664.     new_free(&tmp);
  3665. }
  3666.  
  3667. #endif
  3668.  
  3669.  
  3670.  
  3671.  
  3672. void dcc_check_idle _((void))
  3673. {
  3674. register DCC_list *Client = NULL, *tmpClient;
  3675.  
  3676. time_t dcc_idle_time = get_int_var(_CDCC_CLOSE_IDLE_SENDS_TIME_VAR);
  3677. static char *last_notify = NULL;
  3678. int minidlecheck = get_int_var(_CDCC_MINSPEED_TIME_VAR);
  3679.  
  3680.     if (dcc_idle_time)
  3681.     {
  3682.         int this_idle_time = dcc_idle_time;
  3683.         int erase_it;
  3684.         for (Client = ClientList; Client;)
  3685.         {
  3686.             time_t client_idle = time(NULL) - Client->lasttime.tv_sec;
  3687.             if (client_idle <= 0 ) client_idle = 1;
  3688.             erase_it = 0;
  3689.             tmpClient = Client->next;
  3690.             switch (Client->flags & DCC_TYPES)
  3691.             {
  3692.                 case DCC_FILEOFFER:
  3693.                 case DCC_FILEREAD:
  3694.                 case DCC_RESENDOFFER:
  3695.                 case DCC_REGETFILE:
  3696.                     this_idle_time = dcc_idle_time * 3;
  3697.                     break;
  3698.                 default:
  3699.                     this_idle_time = dcc_idle_time;
  3700.                     break;
  3701.             }
  3702.             if ((client_idle > this_idle_time) && !(Client->flags&DCC_ACTIVE))
  3703.             {
  3704.                 put_it("%s", convert_output_format("$G %RDCC%n Auto-closing idle dcc $0 to $1", "%s %s", dcc_types[Client->flags&DCC_TYPES], Client->user));
  3705.                 if (!last_notify || strcmp(Client->user,last_notify))
  3706.                 {
  3707.                     send_to_server("NOTICE %s :Dcc %s Auto Closed", Client->user, dcc_types[Client->flags&DCC_TYPES]);
  3708.                     malloc_strcpy(&last_notify, Client->user);
  3709.                 }
  3710.                 if ((get_to_from(dcc_types[Client->flags & DCC_TYPES]) != -1))
  3711.                     if (dcc_active_count)
  3712.                         dcc_active_count--;
  3713.                 erase_it = 1;
  3714.             }
  3715. #ifdef WANT_CDCC
  3716.             if (Client->flags&DCC_ACTIVE)
  3717.             {
  3718.                 switch (Client->flags & DCC_TYPES)
  3719.                 {
  3720.                     case DCC_FILEOFFER:
  3721.                     case DCC_RESENDOFFER:
  3722.                         if (cdcc_minspeed && minidlecheck && ((client_idle % minidlecheck) == 0))
  3723.                         {
  3724.                             unsigned long sent = Client->bytes_sent / 1024;
  3725.                             double this_speed = 0.0;
  3726.                             char lame_ultrix1[20];
  3727.                             char lame_ultrix[20];
  3728.                             this_speed = (double)((double) sent / (double)client_idle);
  3729.  
  3730.                             if (this_speed < cdcc_minspeed)
  3731.                             {
  3732.                                 sprintf(lame_ultrix, "%2.4g", (double)(sent / client_idle));
  3733.                                 sprintf(lame_ultrix1,"%2.4g", (double)cdcc_minspeed);
  3734.                                 put_it("%s", convert_output_format("$G %RDCC%n Auto-closing Slow dcc $0 to $1 require $2KB/s got $3KB/s", "%s %s %s %s", dcc_types[Client->flags&DCC_TYPES], Client->user, lame_ultrix1, lame_ultrix));
  3735.                                 if (!last_notify || strcmp(Client->user,last_notify))
  3736.                                 {
  3737.                                     send_to_server("NOTICE %s :CDCC Slow dcc %s Auto Closed. Require %sKB/s got %sKB/s", Client->user, dcc_types[Client->flags&DCC_TYPES], lame_ultrix1, lame_ultrix);
  3738.                                     malloc_strcpy(&last_notify, Client->user);
  3739.                                 }
  3740.                                 if (dcc_active_count)
  3741.                                     dcc_active_count--;
  3742.                                 erase_it = 1;
  3743.                             }
  3744.                         }
  3745.                     default:
  3746.                         break;
  3747.                 }
  3748.             } 
  3749. #endif
  3750.             if (erase_it)
  3751.                 dcc_erase(Client);
  3752.             Client = tmpClient;
  3753.         }
  3754.     }
  3755. #ifdef WANT_CDCC
  3756.     cdcc_timer_offer();
  3757. #endif
  3758. }
  3759.  
  3760. BUILT_IN_COMMAND(dcx)
  3761. {
  3762. char *user = NULL;
  3763. int do_chat = 0;
  3764. int do_send = 0;
  3765. int do_get = 0;
  3766. int do_all = 0;
  3767. char *nick;
  3768.     context;
  3769.     do_chat = !my_stricmp(command, "dcx");
  3770.     do_send = !my_stricmp(command, "dcs");
  3771.     do_get  = !my_stricmp(command, "dcg");
  3772.     do_all    = !my_stricmp(command, "dca");
  3773.  
  3774.     if (!do_all && !(user = next_arg(args, &args)))
  3775.     {
  3776.         userage(command, helparg);
  3777.         return;
  3778.     }
  3779.  
  3780.     if  (do_all && !user)
  3781.     {
  3782.         dcc_close_all();
  3783.         dcc_active_count = 0;
  3784.         update_all_status(current_window, NULL, 0);
  3785.         return;
  3786.     }
  3787.     while ((nick = next_in_comma_list(user, &user)))
  3788.     {
  3789.         if (!nick || !*nick)
  3790.             break;
  3791.         if (do_send)
  3792.         {
  3793.             dcc_close_type_nick_all("SEND", nick);
  3794.             dcc_close_type_nick_all("RESEND", nick);
  3795.         } 
  3796.         else if (do_get)
  3797.         {
  3798.             dcc_close_type_nick_all("GET", nick);
  3799.             dcc_close_type_nick_all("REGET", nick);
  3800.         } 
  3801.         else if (do_chat)
  3802.             dcc_close_type_nick_all("CHAT", nick);
  3803.     }
  3804.     update_all_status(current_window, NULL, 0);
  3805.     return;
  3806. }
  3807.  
  3808. #ifdef WANT_FTP
  3809. void open_ftpsend (DCC_list *client, char *args)
  3810. {
  3811. struct sockaddr_in data_addr = { 0 };
  3812. int len = sizeof(struct sockaddr_in);
  3813. char tmp[2048];
  3814. int on = 1, data = -1, s1 = -1;
  3815. char *a, *p;
  3816. DCC_list *Client = NULL;
  3817. char *bufptr;
  3818.     if (client->in_ftp)
  3819.     {
  3820.         put_it("%s", convert_output_format("$G %gFTP%n already transfering a file.", NULL, NULL));
  3821.         return;
  3822.     }
  3823.     if (getsockname(client->read, (struct sockaddr *)&data_addr, &len) < 0)
  3824.         return;
  3825.  
  3826.     data_addr.sin_port = 0;
  3827.     if ((data = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  3828.         return;
  3829.     if ((setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
  3830.         return;
  3831.     if ((bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr))) < 0)
  3832.         return;
  3833.     len = sizeof(struct sockaddr_in);
  3834.     getsockname(data, (struct sockaddr *)&data_addr, &len);
  3835.  
  3836.     if ((listen(data, 4)) < 0)
  3837.         return;
  3838.  
  3839.     a = (char *)&data_addr.sin_addr;
  3840.     p = (char *)&data_addr.sin_port;
  3841. #define UC(b) (((int)b)&0xff)
  3842.     dcc_printf(client->read, "PORT %d,%d,%d,%d,%d,%d\n", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),UC(p[0]), UC(p[1]));
  3843. #undef UC
  3844.     dcc_printf(client->read, "stor %s\n", args);
  3845.  
  3846.     memset(tmp, 0, sizeof(tmp));
  3847.     bufptr = tmp;
  3848.     while (1)
  3849.     {
  3850.         if (dgets(bufptr, client->read, 1) == -1 && dgets_errno > 0)
  3851.             goto error_ftpsend;
  3852.         if (*bufptr == '5')
  3853.             goto error_ftpsend;
  3854.         else if (strstr(tmp, "BINARY mode data connection"))
  3855.             break;
  3856.     }
  3857.     len = sizeof(struct sockaddr_in);
  3858.     if ((s1 = accept(data, (struct sockaddr *) &data_addr, &len)) < 0)
  3859.         return;
  3860.     close(data);
  3861.  
  3862.     if ((Client = dcc_searchlist("ftpsend", args, DCC_FTPSEND, 1, client->user, NULL, -1)))
  3863.     {
  3864.         struct stat st;
  3865.         Client->read = Client->write = s1;
  3866. #if defined(WINNT) || defined(__EMX__)
  3867.         Client->file = open(args, O_RDONLY | O_BINARY);
  3868. #else
  3869.         Client->file = open(args, O_RDONLY);
  3870. #endif
  3871.         fstat(Client->file, &st);
  3872.         Client->flags |= DCC_ACTIVE;
  3873.         new_open(Client->read);
  3874.         Client->filesize = st.st_size;
  3875.         get_time(&Client->starttime);
  3876.         client->in_ftp = 1;
  3877.     }
  3878.     return;
  3879. error_ftpsend:
  3880.     close(data);
  3881.     chop(tmp, 2);
  3882.     put_it("%s", convert_output_format("$G %gFTP%n $0-", "%s", tmp));
  3883.     return;
  3884. }
  3885.  
  3886. void open_ftpget(DCC_list *client, char *args)
  3887. {
  3888. struct sockaddr_in data_addr = { 0 };
  3889. int len = sizeof(struct sockaddr_in);
  3890. char tmp[2048];
  3891. int on = 1, data = -1, s1 = -1;
  3892. char *a, *p, *bufptr;
  3893. DCC_list *Client = NULL;
  3894. off_t filesize = 0;
  3895. char *filename = NULL;
  3896.  
  3897.     if (client->in_ftp)
  3898.     {
  3899.         put_it("%s", convert_output_format("$G %gFTP%n already transfering a file.", NULL, NULL));
  3900.         return;
  3901.     }
  3902.     if (getsockname(client->read, (struct sockaddr *)&data_addr, &len) < 0)
  3903.         return;
  3904.  
  3905.     data_addr.sin_port = 0;
  3906.     if ((data = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  3907.         return;
  3908.     if ((setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
  3909.         return;
  3910.     if ((bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr))) < 0)
  3911.         return;
  3912.     len = sizeof(struct sockaddr_in);
  3913.     getsockname(data, (struct sockaddr *)&data_addr, &len);
  3914.  
  3915.     if ((listen(data, 4)) < 0)
  3916.         return;
  3917.  
  3918.     a = (char *)&data_addr.sin_addr;
  3919.     p = (char *)&data_addr.sin_port;
  3920. #define UC(b) (((int)b)&0xff)
  3921.     dcc_printf(client->read, "PORT %d,%d,%d,%d,%d,%d\n", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),UC(p[0]), UC(p[1]));
  3922. #undef UC
  3923.  
  3924.     dcc_printf(client->read, "retr %s\n", args);
  3925.  
  3926.     memset(tmp, 0, sizeof(tmp));
  3927.     bufptr = tmp;
  3928.     while (1)
  3929.     {
  3930.         if (dgets(bufptr, client->read, 1) == -1 && dgets_errno > 0)
  3931.             goto error_ftp;
  3932.         if (*bufptr == '5')
  3933.             goto error_ftp;
  3934.         else if (strstr(tmp, "BINARY mode data connection"))
  3935.         {
  3936.             int i = 0;
  3937.             char *q = tmp;
  3938.             for (i = 0; i < 9; i++)
  3939.                 p = next_arg(q, &q);
  3940.             if (p)
  3941.             {
  3942.                 p++;
  3943.                 filesize = my_atol(p);
  3944.             }
  3945.             break;
  3946.         }
  3947.     }
  3948.  
  3949.     len = sizeof(struct sockaddr_in);
  3950.     if ((s1 = accept(data, (struct sockaddr *) &data_addr, &len)) < 0)
  3951.         return;
  3952.     close(data);
  3953.  
  3954. #if defined(WINNT) || defined(__EMX__)
  3955.     if ((p = strrchr(args, '/')) || (p = strrchr(args, '\\')))
  3956. #else
  3957.     if ((p = strrchr(args, '/')))
  3958. #endif
  3959.         filename = ++p;
  3960.     else
  3961.         filename = args;
  3962.  
  3963.     if ((Client = dcc_searchlist("ftpget", filename, DCC_FTPGET, 1, client->user, NULL, -1)))
  3964.     {
  3965.         Client->read = Client->write = s1;
  3966. #if defined(WINNT) || defined(__EMX__)
  3967.         Client->file = open(filename, O_WRONLY|O_CREAT|O_TRUNC | O_BINARY/*, 0644*/);
  3968. #else
  3969.         Client->file = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
  3970. #endif
  3971.         Client->flags |= DCC_ACTIVE;
  3972.         new_open(Client->read);
  3973.         Client->filesize = filesize;
  3974.         get_time(&Client->starttime);
  3975.         if (do_hook(FTP_LIST, "%s %s", "FTP Attempting to get", filename))
  3976.             put_it("%s", convert_output_format("$G %gFTP%n Attempting to get $0", "%s", filename));
  3977.         client->in_ftp = 1;
  3978.     }
  3979.     return;
  3980. error_ftp:
  3981.     close(data);
  3982.     chop(tmp, 2);
  3983.     put_it("%s", convert_output_format("$G %gFTP%n $0-", "%s", tmp));
  3984.     return;
  3985. }
  3986.  
  3987. int dcc_ftpcommand _((char *host, char *args))
  3988. {
  3989. DCC_list *Client;
  3990.     Client = dcc_searchlist("ftpopen", host, DCC_FTPOPEN, 0, NULL, NULL, -1);
  3991.     if (Client && !Client->in_ftp)
  3992.     {
  3993.         char *command = next_arg(args, &args);
  3994.         char *t_host;
  3995.         if (!my_strnicmp(command, "ls",2) || !my_strnicmp(command, "dir",3))
  3996.             dcc_printf(Client->read, "stat %s\n", (args && *args) ? args : ".");
  3997.         else if (!my_strnicmp(command, "more", 3))
  3998.             dcc_printf(Client->read, "stat %s\n", (args && *args) ? "cwd" : "pwd", (args && *args) ?args:empty_string);
  3999.         else if (!my_strnicmp(command, "cd", 2))
  4000.             dcc_printf(Client->read, "%s%s%s\n", (args && *args) ? "cwd" : "pwd", (args && *args) ? " ":empty_string, (args && *args) ?args:empty_string);
  4001.         else if (!my_strnicmp(command, "get",3) && args && *args)
  4002.             open_ftpget(Client, args);
  4003.         else if (!my_strnicmp(command, "put",3) && args && *args)
  4004.             open_ftpsend(Client, args);
  4005.         else
  4006.             dcc_printf(Client->read, "%s%s%s\n", command, (args && *args) ? " ":empty_string, (args && *args) ? args:empty_string);
  4007.         t_host = alloca(strlen(host)+4);
  4008.         strcpy(t_host, "-"); strcat(t_host, host);
  4009.         addtabkey(t_host, "msg", 0);
  4010.     }
  4011.     else if (Client && Client->in_ftp)
  4012.     {
  4013.         if (do_hook(FTP_LIST, "%s", "FTP transfering a file"))
  4014.             put_it("%s", convert_output_format("$G %gFTP%n transfering a file.", NULL, NULL));
  4015.         return  0;
  4016.     }
  4017.     else
  4018.     {
  4019.         if (do_hook(FTP_LIST, "%s", "FTP is not connected"))
  4020.             put_it("%s", convert_output_format("$G %gFTP%n is not connected.", NULL, NULL));
  4021.         return 0;
  4022.     }
  4023.     return 1;
  4024. }
  4025.  
  4026. void dcc_ftpopen(char *command, char *args )
  4027. {
  4028. DCC_list *Client;
  4029. char user[] = "anonymous";
  4030. char pass[] = "- bxuser@";
  4031. char *host, *u = user, *p = pass;
  4032. char *t_host;
  4033. int port = 21;
  4034.  
  4035.     if (!(host = next_arg(args, &args)))
  4036.     {
  4037.         put_it ("%s /dcc ftp hostname user passwd [-p port]", convert_output_format("$G %RDCC%n", NULL, NULL));
  4038.         return;
  4039.     }
  4040.     u = user;
  4041.     p = pass;
  4042.     while (args && *args)
  4043.     {
  4044.         if (args && *args && *args == '-' && *(args+1) == 'p')    
  4045.         {
  4046.             char *t;
  4047.             t = next_arg(args, &args);
  4048.             t = next_arg(args, &args);
  4049.             if (t)
  4050.                 port = my_atol(t);
  4051.             break;
  4052.         }
  4053.         if (!(u = next_arg(args, &args)))
  4054.             u = user;
  4055.         if (!(p = next_arg(args, &args)))
  4056.             p = pass;
  4057.     }
  4058.     
  4059.     Client = dcc_searchlist("ftpopen", host, DCC_FTPOPEN, 1, NULL, NULL, -1);
  4060.     if (!Client) return;
  4061.     
  4062.     if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  4063.     {
  4064.         put_it("%s", convert_output_format("$G %GFTP%n A previous DCC FTP to $0 exists", "%s", host));
  4065.         return;
  4066.     }
  4067.     Client->remport = port;
  4068.     malloc_strcpy(&Client->encrypt, p);
  4069.     malloc_strcpy(&Client->user, host);
  4070.     malloc_strcpy(&Client->othername, u);
  4071.         
  4072. #if defined(WINNT) || defined(__EMX__)
  4073.     if ((Client->read = connect_by_number(host, &Client->remport, SERVICE_CLIENT, PROTOCOL_TCP, 0)) < 0)
  4074. #else
  4075.     if ((Client->read = connect_by_number(host, &Client->remport, SERVICE_CLIENT, PROTOCOL_TCP, 1)) < 0)
  4076. #endif
  4077.     {
  4078.         Client->flags |= DCC_DELETE;
  4079.         put_it("%s", convert_output_format("$G %gFTP%n command failed connect", NULL, NULL));
  4080.         return;
  4081.     }
  4082.     Client->remport = ntohs(Client->remport);
  4083. #ifdef DCC_CNCT_PEND
  4084.     Client->flags |= DCC_WAIT|DCC_CNCT_PEND;
  4085. #else
  4086.     Client->flags |= DCC_WAIT;
  4087. #endif
  4088.  
  4089.     new_open(Client->read);
  4090.     t_host = alloca(strlen(host)+4);
  4091.     strcpy(t_host, "-"); strcat(t_host, host);
  4092.     addtabkey(t_host, "msg", 0);
  4093. }
  4094.  
  4095. static void dcc_ftpget (char *command, char *args)
  4096. {
  4097. char *host; char *file = NULL;
  4098. DCC_list *Client;
  4099.     if (!(host = next_arg(args, &args)))
  4100.     {
  4101.         return;
  4102.     }
  4103.     if (args && *args)
  4104.         file = next_arg(args, &args);
  4105.         
  4106.     Client = dcc_searchlist(file, host, DCC_XMITRECV, 1, NULL, NULL, -1);
  4107.     if (Client)
  4108.     {
  4109.         Client->flags &=DCC_WAIT;
  4110.         new_open(Client->read);
  4111.     }
  4112.  
  4113. }
  4114.  
  4115. #ifdef FTP_XMIT
  4116. static void dcc_xmitget (char *user, char *description, char *address, char *port)
  4117. {
  4118. DCC_list *Client;
  4119. unsigned long TempLong;
  4120. unsigned int TempInt;
  4121. unsigned short TempSh;
  4122.  
  4123. #ifdef PUBLIC_ACCESS
  4124.     bitchsay("This command has been disabled on a public access system");
  4125. #endif
  4126.     Client = dcc_searchlist(description, user, DCC_XMITRECV, 1, NULL, NULL, -1);
  4127.  
  4128.     if (Client->flags & DCC_ACTIVE)
  4129.     {
  4130.         put_it("%s", convert_output_format("$G %RDCC%n Recieved DCC $0 request from $1 while previous session active", "%s %s", "XMIT", user));
  4131.         message_from(NULL, LOG_CRAP);
  4132.         return;
  4133.     }
  4134.     Client->flags |= DCC_OFFER;
  4135.  
  4136.     TempLong = strtoul(address, NULL, 10);
  4137.     Client->remote.s_addr = htonl(TempLong);
  4138.     TempSh = TempInt = (unsigned) strtoul(port, NULL, 10);
  4139.     Client->remport = htons(TempInt);
  4140. #if defined(WINNT) || defined(__EMX__)
  4141.     if ((Client->read = connect_by_number(address, &TempSh, SERVICE_SERVER, PROTOCOL_TCP, 0)) < 0)
  4142. #else
  4143.     if ((Client->read = connect_by_number(address, &TempSh, SERVICE_SERVER, PROTOCOL_TCP, 1)) < 0)
  4144. #endif
  4145.     {
  4146.         Client->flags |= DCC_DELETE;
  4147.         return;
  4148.     }
  4149. /*    FD_SET(Client->read, &readables);*/
  4150.     new_open(Client->read);
  4151. }
  4152. #endif
  4153.  
  4154. static void dcc_ftpsend (char *command, char *args)
  4155. {
  4156.  
  4157.     char        *user = NULL;
  4158.     char        *filename = NULL, *p;
  4159.     struct    in_addr    myip;
  4160.     char        *tmp = NULL;
  4161.     DCC_list    *Client = NULL;
  4162.     unsigned short    portnum;
  4163.     char         *fullname = NULL;
  4164.     struct stat st;
  4165.     
  4166. #ifdef PUBLIC_ACCESS
  4167.     bitchsay("This command has been disabled on a public access system");
  4168. #endif
  4169.     if (!(user = next_arg(args, &args)) || !(filename = next_arg(args, &args)))
  4170.     {
  4171.         say("You must supply a nickname and a filename for DCC XMIT");
  4172.         return;
  4173.     }
  4174.  
  4175. #ifndef WINNT
  4176.     if (scanstr("/etc/", filename))
  4177.     {
  4178.         put_it("%s", convert_output_format("$G %RDCC%n Send request for /etc rejected", NULL, NULL));
  4179.         return;
  4180.     }
  4181. #endif
  4182.     fullname = expand_twiddle(filename);
  4183.     Client = dcc_searchlist(filename, user, DCC_XMITSEND, 1, fullname, NULL, -1);
  4184.     if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  4185.     {
  4186.         put_it("%s", convert_output_format("$G %RDCC%n A previous DCC send:$0 to $1 exists", "%s %s", filename, user));
  4187.         return;
  4188.     }
  4189.  
  4190. #if defined(WINNT) || defined(__EMX__)
  4191.     if ((Client->read = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 0)) < 0)
  4192. #else
  4193.     if ((Client->read = connect_by_number(NULL, &portnum, SERVICE_SERVER, PROTOCOL_TCP, 1)) < 0)
  4194. #endif
  4195.     {
  4196.         put_it("%s", convert_output_format("$G %RDCC%n Unable to create connection: $0-", "%s", errno ? strerror(errno) : "Unknown Host"));
  4197.         message_from(NULL, LOG_CRAP);
  4198.         dcc_erase(Client);
  4199.         return;
  4200.     }
  4201.     Client->remport = htons(portnum);
  4202.     new_open(Client->read);
  4203.     myip.s_addr = server_list[from_server].local_addr.s_addr;
  4204.  
  4205.  
  4206.     if (myip.s_addr == htonl(0x7f000001))
  4207.         myip.s_addr = MyHostAddr.s_addr;
  4208.  
  4209. #if defined(WINNT) || defined(__EMX__)
  4210.     if ((p = strrchr(filename, '/')) || (p = strrchr(filename, '\\')))
  4211. #else        
  4212.     if ((p = strrchr(filename, '/')))
  4213. #endif
  4214.         malloc_strcpy(&tmp, ++p); 
  4215.     else
  4216.         tmp = m_strdup(filename);
  4217.     stat(fullname, &st);
  4218.     Client->filesize = st.st_size;
  4219.     send_ctcp(CTCP_PRIVMSG, user, CTCP_XMIT, "clear %lu %d %s", 
  4220.         (unsigned long)htonl(myip.s_addr), Client->remport, tmp);
  4221. #ifdef DCC_CNCT_PEND
  4222.     Client->flags |= DCC_WAIT|DCC_CNCT_PEND;
  4223. #else
  4224.     Client->flags |= DCC_WAIT;
  4225. #endif
  4226.     new_free(&tmp);
  4227. }
  4228.  
  4229. static void process_incoming_ftp (register DCC_list *client)
  4230. {
  4231. char tmp[MAX_DCC_BLOCK_SIZE * 4 + 1];
  4232. unsigned int bytesread = 0;
  4233. char *bufptr;
  4234.     if ((client->flags & DCC_TYPES) == DCC_FTPGET)
  4235.     {
  4236.         DCC_list *new = NULL;
  4237.         if ((bytesread = read(client->write, &tmp, sizeof(tmp)-1)) > 0)
  4238.         {
  4239.             client->bytes_read +=bytesread;
  4240.             client->packets_transfer++;
  4241.             if ((write(client->file, tmp, bytesread)) != bytesread)
  4242.             {
  4243.                 client->flags |= DCC_DELETE;
  4244.                 client->read = -1;
  4245.                 if ((new = dcc_searchlist("ftpopen", client->othername, DCC_FTPOPEN, 0, NULL, NULL, 1)))
  4246.                     new->in_ftp = 0;
  4247.             }
  4248.         }
  4249.         else
  4250.         {
  4251.             if ((new = dcc_searchlist("ftpopen", client->othername, DCC_FTPOPEN, 0, NULL, NULL, 1)))
  4252.                 new->in_ftp = 0;
  4253.             DCC_close_filesend(client, "FTPGET");
  4254.         }
  4255.         return;
  4256.     }
  4257.     if (client->flags & DCC_WAIT)
  4258.     {
  4259.         if ((dcc_printf(client->read, "user %s\n", client->othername) < 0) || (dcc_printf(client->read, "pass %s\n", client->encrypt) < 0))
  4260.         {
  4261.             client->flags |= DCC_DELETE;
  4262.             put_it("%s", convert_output_format("$G %gFTP%n command failed write", NULL, NULL));
  4263.             return;
  4264.         }
  4265.         dcc_printf(client->read, "type i\n");
  4266.         new_free(&client->encrypt);
  4267.  
  4268.         client->flags |= DCC_ACTIVE;
  4269.         client->flags &= ~DCC_WAIT;
  4270.         return;
  4271.     }
  4272.     bufptr = tmp;
  4273.     bytesread = dgets(bufptr, client->read, 1);
  4274.     switch (bytesread)
  4275.     {
  4276.         case -1:
  4277.         {
  4278.             client->flags |= DCC_DELETE;
  4279.             break;
  4280.         }
  4281.         case 0:
  4282.             break;
  4283.         default:
  4284.         {
  4285.             char *num;
  4286.             char *p, *t;
  4287.             chop(tmp, 2);
  4288.             t = p = m_strdup(tmp);
  4289.             num = next_arg(p, &p);
  4290.             message_from(client->user, LOG_DCC);
  4291.             if (do_hook(FTP_LIST, "%s %s", num, p))
  4292.             {
  4293.                 if (num && isdigit(*num))
  4294.                     put_it("%s", convert_output_format("$G %gFTP%n $0-", "%s", p));
  4295.                 else
  4296.                     put_it("%s", convert_output_format(tmp, NULL, NULL));
  4297.             }
  4298.             new_free(&t);
  4299.         }
  4300.     }
  4301.     message_from(NULL, LOG_CRAP);
  4302. }
  4303.  
  4304. static void process_outgoing_ftp (DCC_list *client)
  4305. {
  4306. char tmp[MAX_DCC_BLOCK_SIZE * 4 + 1];
  4307. unsigned int bytesread = 0;
  4308. DCC_list *new = NULL;
  4309.     if ((bytesread = read(client->file, &tmp, sizeof(tmp)-1)) > 0)
  4310.     {
  4311.         client->bytes_sent +=bytesread;
  4312.         client->packets_transfer++;
  4313.         if ((send(client->write, tmp, bytesread, 0)) != bytesread)
  4314.         {
  4315.             client->flags |= DCC_DELETE;
  4316.             if ((new = dcc_searchlist("ftpopen", client->othername, DCC_FTPOPEN, 0, NULL, NULL, 1)))
  4317.                 new->in_ftp = 0;
  4318.         }
  4319.     }
  4320.     else
  4321.     {
  4322.         if ((new = dcc_searchlist("ftpopen", client->othername, DCC_FTPOPEN, 0, NULL, NULL, 1)))
  4323.             new->in_ftp = 0;
  4324.         DCC_close_filesend(client, "FTPSEND");
  4325.     }
  4326.     return;
  4327. }
  4328. #endif
  4329.  
  4330. int check_dcc_list (char *name)
  4331. {
  4332. register DCC_list *Client;
  4333. int do_it = 0;
  4334.     for (Client = ClientList; Client; Client = Client->next)
  4335.     {
  4336.         if (Client->user && !my_stricmp(name, Client->user) && !(Client->flags & DCC_ACTIVE))
  4337.         {
  4338.             Client->flags |= DCC_DELETE;
  4339.             do_it++;
  4340.             if (get_to_from(dcc_types[Client->flags&DCC_TYPES]) != -1 && dcc_active_count)
  4341.                 dcc_active_count--;
  4342.         }
  4343.     }
  4344.     return do_it;
  4345. }
  4346.  
  4347. void dcc_nick (char *command, char *args)
  4348. {
  4349. int remove;
  4350. List *nptr = NULL;
  4351. char *nick;
  4352.     if (!args || !*args)
  4353.     {
  4354.         int count = 0;
  4355.         for (nptr = next_namelist(dcc_no_flood, NULL, DCC_HASHSIZE); nptr; nptr = next_namelist(dcc_no_flood, nptr, DCC_HASHSIZE))
  4356.         {
  4357.             if (count == 0)
  4358.                 put_it("%s", convert_output_format("$G %RDCC%n autoget list/no flood list", NULL, NULL));
  4359.             put_it("%s", nptr->name);
  4360.             count++;
  4361.         }
  4362.         if (count == 0)
  4363.             userage("/dcc exempt", "+nick to add, nick to remove"); 
  4364.         return;
  4365.     }
  4366.     nick = next_arg(args, &args);
  4367.     while (nick && *nick)
  4368.     {
  4369.         remove = 1;
  4370.         if (*nick == '+')
  4371.         {
  4372.             remove = 0;
  4373.             nick++;
  4374.         }
  4375.         nptr = find_name_in_genericlist(nick, dcc_no_flood, DCC_HASHSIZE, remove);
  4376.         if (remove && nptr)
  4377.         {
  4378.             new_free(&nptr->name);
  4379.             new_free((char **)&nptr);
  4380.         }
  4381.         else if (!remove && !nptr)
  4382.             add_name_to_genericlist(nick, dcc_no_flood, DCC_HASHSIZE);
  4383.         else if (remove && !nptr)
  4384.             put_it("%s", convert_output_format("$G: %RDCC%n No such nick on the exempt list %K[%W$0%K]", "%s", nick));
  4385.         nick = next_arg(args, &args);
  4386.     }
  4387. }
  4388.  
  4389. int dcc_exempt_save(FILE *fptr)
  4390. {
  4391. int count = 0;
  4392. List *nptr = NULL;
  4393.     if (dcc_no_flood)
  4394.     {
  4395.         fprintf(fptr, "# Dcc Exempt from autoget OFF list\n");
  4396.         fprintf(fptr, "DCC EXEMPT ");
  4397.     }
  4398.     for (nptr = next_namelist(dcc_no_flood, NULL, DCC_HASHSIZE); nptr; nptr = next_namelist(dcc_no_flood, nptr, DCC_HASHSIZE))
  4399.     {
  4400.         fprintf(fptr, "+%s ", nptr->name);
  4401.         count++;
  4402.     }
  4403.     if (dcc_no_flood)
  4404.     {
  4405.         fprintf(fptr, "\n");
  4406.         if (count && do_hook(SAVEFILE_LIST, "DCCexempt %d", count))
  4407.             bitchsay("Saved %d DccExempt entries", count);
  4408.                                 
  4409.     }
  4410.     return count;
  4411. }
  4412.